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
115 #if !defined(_WIN32) && !defined(CONFIG_TCCBOOT)
116 #define CONFIG_TCC_BACKTRACE
125 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
126 executables or dlls */
127 #define CONFIG_TCC_CRT_PREFIX CONFIG_SYSROOT "/usr/lib"
129 #define INCLUDE_STACK_SIZE 32
130 #define IFDEF_STACK_SIZE 64
131 #define VSTACK_SIZE 256
132 #define STRING_MAX_SIZE 1024
133 #define PACK_STACK_SIZE 8
135 #define TOK_HASH_SIZE 8192 /* must be a power of two */
136 #define TOK_ALLOC_INCR 512 /* must be a power of two */
137 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
139 /* token symbol management */
140 typedef struct TokenSym
{
141 struct TokenSym
*hash_next
;
142 struct Sym
*sym_define
; /* direct pointer to define */
143 struct Sym
*sym_label
; /* direct pointer to label */
144 struct Sym
*sym_struct
; /* direct pointer to structure */
145 struct Sym
*sym_identifier
; /* direct pointer to identifier */
146 int tok
; /* token number */
152 typedef unsigned short nwchar_t
;
154 typedef int nwchar_t
;
157 typedef struct CString
{
158 int size
; /* size in bytes */
159 void *data
; /* either 'char *' or 'nwchar_t *' */
161 void *data_allocated
; /* if non NULL, data has been malloced */
164 /* type definition */
165 typedef struct CType
{
171 typedef union CValue
{
177 unsigned int ul
; /* address (should be unsigned long on 64 bit cpu) */
179 unsigned long long ull
;
180 struct CString
*cstr
;
186 typedef struct SValue
{
187 CType type
; /* type */
188 unsigned short r
; /* register + flags */
189 unsigned short r2
; /* second register, used for 'long long'
190 type. If not used, set to VT_CONST */
191 CValue c
; /* constant, if VT_CONST */
192 struct Sym
*sym
; /* symbol, if (VT_SYM | VT_CONST) */
195 /* symbol management */
197 int v
; /* symbol token */
198 long r
; /* associated register */
199 long c
; /* associated number */
200 CType type
; /* associated type */
201 struct Sym
*next
; /* next related symbol */
202 struct Sym
*prev
; /* prev symbol in stack */
203 struct Sym
*prev_tok
; /* previous symbol for this token */
206 /* section definition */
207 /* XXX: use directly ELF structure for parameters ? */
208 /* special flag to indicate that the section should not be linked to
210 #define SHF_PRIVATE 0x80000000
212 typedef struct Section
{
213 unsigned long data_offset
; /* current data offset */
214 unsigned char *data
; /* section data */
215 unsigned long data_allocated
; /* used for realloc() handling */
216 int sh_name
; /* elf section name (only used during output) */
217 int sh_num
; /* elf section number */
218 int sh_type
; /* elf section type */
219 int sh_flags
; /* elf section flags */
220 int sh_info
; /* elf section info */
221 int sh_addralign
; /* elf section alignment */
222 int sh_entsize
; /* elf entry size */
223 unsigned long sh_size
; /* section size (only used during output) */
224 unsigned long sh_addr
; /* address at which the section is relocated */
225 unsigned long sh_offset
; /* file offset */
226 int nb_hashed_syms
; /* used to resize the hash table */
227 struct Section
*link
; /* link to another section */
228 struct Section
*reloc
; /* corresponding section for relocation, if any */
229 struct Section
*hash
; /* hash table for symbols */
230 struct Section
*next
;
231 char name
[1]; /* section name */
234 typedef struct DLLReference
{
240 /* GNUC attribute definition */
241 typedef struct AttributeDef
{
245 int func_attr
; /* calling convention, exports, ... */
248 /* -------------------------------------------------- */
249 /* gr: wrappers for casting sym->r for other purposes */
257 #define FUNC_CALL(r) (((func_attr_t*)&(r))->func_call)
258 #define FUNC_EXPORT(r) (((func_attr_t*)&(r))->func_export)
259 #define FUNC_ARGS(r) (((func_attr_t*)&(r))->func_args)
260 #define INLINE_DEF(r) (*(int **)&(r))
261 /* -------------------------------------------------- */
263 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
264 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
265 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
267 /* stored in 'Sym.c' field */
268 #define FUNC_NEW 1 /* ansi function prototype */
269 #define FUNC_OLD 2 /* old function prototype */
270 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
272 /* stored in 'Sym.r' field */
273 #define FUNC_CDECL 0 /* standard c call */
274 #define FUNC_STDCALL 1 /* pascal c call */
275 #define FUNC_FASTCALL1 2 /* first param in %eax */
276 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
277 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
278 #define FUNC_FASTCALLW 5 /* first parameter in %ecx, %edx */
280 /* field 'Sym.t' for macros */
281 #define MACRO_OBJ 0 /* object like macro */
282 #define MACRO_FUNC 1 /* function like macro */
284 /* field 'Sym.r' for C labels */
285 #define LABEL_DEFINED 0 /* label is defined */
286 #define LABEL_FORWARD 1 /* label is forward defined */
287 #define LABEL_DECLARED 2 /* label is declared but never used */
289 /* type_decl() types */
290 #define TYPE_ABSTRACT 1 /* type without variable */
291 #define TYPE_DIRECT 2 /* type with variable */
293 #define IO_BUF_SIZE 8192
295 typedef struct BufferedFile
{
299 int line_num
; /* current line number - here to simplify code */
300 int ifndef_macro
; /* #ifndef macro / #endif search */
301 int ifndef_macro_saved
; /* saved ifndef_macro */
302 int *ifdef_stack_ptr
; /* ifdef_stack value at the start of the file */
303 char inc_type
; /* type of include */
304 char inc_filename
[512]; /* filename specified by the user */
305 char filename
[1024]; /* current filename - here to simplify code */
306 unsigned char buffer
[IO_BUF_SIZE
+ 1]; /* extra size for CH_EOB char */
309 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
310 #define CH_EOF (-1) /* end of file */
312 /* parsing state (used to save parser state to reparse part of the
313 source several times) */
314 typedef struct ParseState
{
321 /* used to record tokens */
322 typedef struct TokenString
{
329 /* include file cache, used to find files faster and also to eliminate
330 inclusion if the include file is protected by #ifndef ... #endif */
331 typedef struct CachedInclude
{
333 int hash_next
; /* -1 if none */
334 char type
; /* '"' or '>' to give include type */
335 char filename
[1]; /* path specified in #include */
338 #define CACHED_INCLUDES_HASH_SIZE 512
341 static struct BufferedFile
*file
;
344 static CString tokcstr
; /* current parsed string, if any */
345 /* additional informations about token */
346 static int tok_flags
;
347 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
348 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
349 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
350 #define TOK_FLAG_EOF 0x0008 /* end of file */
352 static int *macro_ptr
, *macro_ptr_allocated
;
353 static int *unget_saved_macro_ptr
;
354 static int unget_saved_buffer
[TOK_MAX_SIZE
+ 1];
355 static int unget_buffer_enabled
;
356 static int parse_flags
;
357 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
358 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
359 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
360 token. line feed is also
362 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
363 #define PARSE_FLAG_SPACES 0x0010 /* next() returns space tokens (for -E) */
365 static Section
*text_section
, *data_section
, *bss_section
; /* predefined sections */
366 static Section
*cur_text_section
; /* current section where function code is
368 #ifdef CONFIG_TCC_ASM
369 static Section
*last_text_section
; /* to handle .previous asm directive */
371 /* bound check related sections */
372 static Section
*bounds_section
; /* contains global data bound description */
373 static Section
*lbounds_section
; /* contains local data bound description */
374 /* symbol sections */
375 static Section
*symtab_section
, *strtab_section
;
378 static Section
*stab_section
, *stabstr_section
;
380 /* loc : local variable index
381 ind : output code index
383 anon_sym: anonymous symbol index
385 static int rsym
, anon_sym
, ind
, loc
;
386 /* expression generation modifiers */
387 static int const_wanted
; /* true if constant wanted */
388 static int nocode_wanted
; /* true if no code generation wanted for an expression */
389 static int global_expr
; /* true if compound literals must be allocated
390 globally (used during initializers parsing */
391 static CType func_vt
; /* current function return type (used by return
394 static int last_line_num
, last_ind
, func_ind
; /* debug last line number and pc */
395 static int tok_ident
;
396 static TokenSym
**table_ident
;
397 static TokenSym
*hash_ident
[TOK_HASH_SIZE
];
398 static char token_buf
[STRING_MAX_SIZE
+ 1];
399 static char *funcname
;
400 static Sym
*global_stack
, *local_stack
;
401 static Sym
*define_stack
;
402 static Sym
*global_label_stack
, *local_label_stack
;
403 /* symbol allocator */
404 #define SYM_POOL_NB (8192 / sizeof(Sym))
405 static Sym
*sym_free_first
;
406 static void **sym_pools
;
407 static int nb_sym_pools
;
409 static SValue vstack
[VSTACK_SIZE
], *vtop
;
410 /* some predefined types */
411 static CType char_pointer_type
, func_old_type
, int_type
;
412 /* true if isid(c) || isnum(c) */
413 static unsigned char isidnum_table
[256-CH_EOF
];
415 /* display some information during compilation */
416 static int verbose
= 0;
418 /* compile with debug symbol (and use them if error during execution) */
419 static int do_debug
= 0;
421 /* compile with built-in memory and bounds checker */
422 static int do_bounds_check
= 0;
424 /* display benchmark infos */
426 static int do_bench
= 0;
428 static int total_lines
;
429 static int total_bytes
;
431 /* use GNU C extensions */
432 static int gnu_ext
= 1;
434 /* use Tiny C extensions */
435 static int tcc_ext
= 1;
437 /* max number of callers shown if error */
438 #ifdef CONFIG_TCC_BACKTRACE
439 static int num_callers
= 6;
440 static const char **rt_bound_error_msg
;
443 /* XXX: get rid of this ASAP */
444 static struct TCCState
*tcc_state
;
446 /* give the path of the tcc libraries */
447 static const char *tcc_lib_path
= CONFIG_TCCDIR
;
452 BufferedFile
**include_stack_ptr
;
453 int *ifdef_stack_ptr
;
455 /* include file handling */
456 char **include_paths
;
457 int nb_include_paths
;
458 char **sysinclude_paths
;
459 int nb_sysinclude_paths
;
460 CachedInclude
**cached_includes
;
461 int nb_cached_includes
;
463 char **library_paths
;
464 int nb_library_paths
;
466 /* array of all loaded dlls (including those referenced by loaded
468 DLLReference
**loaded_dlls
;
473 int nb_sections
; /* number of sections, including first dummy section */
475 Section
**priv_sections
;
476 int nb_priv_sections
; /* number of private sections */
481 unsigned long *got_offsets
;
483 /* give the correspondance from symtab indexes to dynsym indexes */
484 int *symtab_to_dynsym
;
486 /* temporary dynamic symbol sections (for dll loading) */
487 Section
*dynsymtab_section
;
488 /* exported dynamic symbol section */
491 int nostdinc
; /* if true, no standard headers are added */
492 int nostdlib
; /* if true, no standard libraries are added */
494 int nocommon
; /* if true, do not use common symbols for .bss data */
496 /* if true, static linking is performed */
499 /* soname as specified on the command line (-soname) */
502 /* if true, all symbols are exported */
505 /* if true, only link in referenced objects from archive */
508 /* address of text section */
509 unsigned long text_addr
;
512 /* output format, see TCC_OUTPUT_FORMAT_xxx */
515 /* C language options */
516 int char_is_unsigned
;
517 int leading_underscore
;
519 /* warning switches */
520 int warn_write_strings
;
521 int warn_unsupported
;
524 int warn_implicit_function_declaration
;
528 void (*error_func
)(void *opaque
, const char *msg
);
529 int error_set_jmp_enabled
;
530 jmp_buf error_jmp_buf
;
533 /* tiny assembler state */
536 /* see include_stack_ptr */
537 BufferedFile
*include_stack
[INCLUDE_STACK_SIZE
];
539 /* see ifdef_stack_ptr */
540 int ifdef_stack
[IFDEF_STACK_SIZE
];
542 /* see cached_includes */
543 int cached_includes_hash
[CACHED_INCLUDES_HASH_SIZE
];
546 int pack_stack
[PACK_STACK_SIZE
];
549 /* output file for preprocessing */
552 /* for tcc_relocate */
555 #ifdef TCC_TARGET_X86_64
556 /* write PLT and GOT here */
557 char *runtime_plt_and_got
;
558 unsigned int runtime_plt_and_got_offset
;
562 /* The current value can be: */
563 #define VT_VALMASK 0x00ff
564 #define VT_CONST 0x00f0 /* constant in vc
565 (must be first non register value) */
566 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
567 #define VT_LOCAL 0x00f2 /* offset on stack */
568 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
569 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
570 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
571 #define VT_LVAL 0x0100 /* var is an lvalue */
572 #define VT_SYM 0x0200 /* a symbol value is added */
573 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
574 char/short stored in integer registers) */
575 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
576 dereferencing value */
577 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
578 bounding function call point is in vc */
579 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
580 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
581 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
582 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
585 #define VT_INT 0 /* integer type */
586 #define VT_BYTE 1 /* signed byte type */
587 #define VT_SHORT 2 /* short type */
588 #define VT_VOID 3 /* void type */
589 #define VT_PTR 4 /* pointer */
590 #define VT_ENUM 5 /* enum definition */
591 #define VT_FUNC 6 /* function type */
592 #define VT_STRUCT 7 /* struct/union definition */
593 #define VT_FLOAT 8 /* IEEE float */
594 #define VT_DOUBLE 9 /* IEEE double */
595 #define VT_LDOUBLE 10 /* IEEE long double */
596 #define VT_BOOL 11 /* ISOC99 boolean type */
597 #define VT_LLONG 12 /* 64 bit integer */
598 #define VT_LONG 13 /* long integer (NEVER USED as type, only
600 #define VT_BTYPE 0x000f /* mask for basic type */
601 #define VT_UNSIGNED 0x0010 /* unsigned type */
602 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
603 #define VT_BITFIELD 0x0040 /* bitfield modifier */
604 #define VT_CONSTANT 0x0800 /* const modifier */
605 #define VT_VOLATILE 0x1000 /* volatile modifier */
606 #define VT_SIGNED 0x2000 /* signed type */
609 #define VT_EXTERN 0x00000080 /* extern definition */
610 #define VT_STATIC 0x00000100 /* static variable */
611 #define VT_TYPEDEF 0x00000200 /* typedef definition */
612 #define VT_INLINE 0x00000400 /* inline definition */
614 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
616 /* type mask (except storage) */
617 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
618 #define VT_TYPE (~(VT_STORAGE))
622 /* warning: the following compare tokens depend on i386 asm code */
629 #define TOK_Nset 0x98
630 #define TOK_Nclear 0x99
636 #define TOK_LAND 0xa0
640 #define TOK_MID 0xa3 /* inc/dec, to void constant */
642 #define TOK_UDIV 0xb0 /* unsigned division */
643 #define TOK_UMOD 0xb1 /* unsigned modulo */
644 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
645 #define TOK_CINT 0xb3 /* number in tokc */
646 #define TOK_CCHAR 0xb4 /* char constant in tokc */
647 #define TOK_STR 0xb5 /* pointer to string in tokc */
648 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
649 #define TOK_LCHAR 0xb7
650 #define TOK_LSTR 0xb8
651 #define TOK_CFLOAT 0xb9 /* float constant */
652 #define TOK_LINENUM 0xba /* line number info */
653 #define TOK_CDOUBLE 0xc0 /* double constant */
654 #define TOK_CLDOUBLE 0xc1 /* long double constant */
655 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
656 #define TOK_ADDC1 0xc3 /* add with carry generation */
657 #define TOK_ADDC2 0xc4 /* add with carry use */
658 #define TOK_SUBC1 0xc5 /* add with carry generation */
659 #define TOK_SUBC2 0xc6 /* add with carry use */
660 #define TOK_CUINT 0xc8 /* unsigned int constant */
661 #define TOK_CLLONG 0xc9 /* long long constant */
662 #define TOK_CULLONG 0xca /* unsigned long long constant */
663 #define TOK_ARROW 0xcb
664 #define TOK_DOTS 0xcc /* three dots */
665 #define TOK_SHR 0xcd /* unsigned shift right */
666 #define TOK_PPNUM 0xce /* preprocessor number */
668 #define TOK_SHL 0x01 /* shift left */
669 #define TOK_SAR 0x02 /* signed shift right */
671 /* assignement operators : normal operator or 0x80 */
672 #define TOK_A_MOD 0xa5
673 #define TOK_A_AND 0xa6
674 #define TOK_A_MUL 0xaa
675 #define TOK_A_ADD 0xab
676 #define TOK_A_SUB 0xad
677 #define TOK_A_DIV 0xaf
678 #define TOK_A_XOR 0xde
679 #define TOK_A_OR 0xfc
680 #define TOK_A_SHL 0x81
681 #define TOK_A_SAR 0x82
684 #define offsetof(type, field) ((size_t) &((type *)0)->field)
688 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
691 /* WARNING: the content of this string encodes token numbers */
692 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";
694 #define TOK_EOF (-1) /* end of file */
695 #define TOK_LINEFEED 10 /* line feed */
697 /* all identificators and strings have token above that */
698 #define TOK_IDENT 256
700 /* only used for i386 asm opcodes definitions */
701 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
704 DEF(TOK_ASM_ ## x ## b, #x "b") \
705 DEF(TOK_ASM_ ## x ## w, #x "w") \
706 DEF(TOK_ASM_ ## x ## l, #x "l") \
707 DEF(TOK_ASM_ ## x, #x)
710 DEF(TOK_ASM_ ## x ## w, #x "w") \
711 DEF(TOK_ASM_ ## x ## l, #x "l") \
712 DEF(TOK_ASM_ ## x, #x)
715 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
716 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
717 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
718 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
721 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
722 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
725 #define DEF_ASMTEST(x) \
757 #define TOK_ASM_int TOK_INT
760 TOK_LAST
= TOK_IDENT
- 1,
761 #define DEF(id, str) id,
766 static const char tcc_keywords
[] =
767 #define DEF(id, str) str "\0"
772 #define TOK_UIDENT TOK_DEFINE
775 #define snprintf _snprintf
776 #define vsnprintf _vsnprintf
778 #define strtold (long double)strtod
779 #define strtof (float)strtod
780 #define strtoll (long long)strtol
782 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__) || defined(__DragonFly__) \
783 || defined(__OpenBSD__)
784 /* currently incorrect */
785 long double strtold(const char *nptr
, char **endptr
)
787 return (long double)strtod(nptr
, endptr
);
789 float strtof(const char *nptr
, char **endptr
)
791 return (float)strtod(nptr
, endptr
);
794 /* XXX: need to define this to use them in non ISOC99 context */
795 extern float strtof (const char *__nptr
, char **__endptr
);
796 extern long double strtold (const char *__nptr
, char **__endptr
);
799 static char *pstrcpy(char *buf
, int buf_size
, const char *s
);
800 static char *pstrcat(char *buf
, int buf_size
, const char *s
);
801 static char *tcc_basename(const char *name
);
802 static char *tcc_fileextension (const char *p
);
804 static void next(void);
805 static void next_nomacro(void);
806 static void next_nomacro_spc(void);
807 static void parse_expr_type(CType
*type
);
808 static void expr_type(CType
*type
);
809 static void unary_type(CType
*type
);
810 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
811 int case_reg
, int is_expr
);
812 static int expr_const(void);
813 static void expr_eq(void);
814 static void gexpr(void);
815 static void gen_inline_functions(void);
816 static void decl(int l
);
817 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
818 int first
, int size_only
);
819 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
820 int has_init
, int v
, int scope
);
822 void gv2(int rc1
, int rc2
);
823 void move_reg(int r
, int s
);
824 void save_regs(int n
);
825 void save_reg(int r
);
830 int get_reg_ex(int rc
,int rc2
);
833 struct macro_level
*prev
;
837 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
838 const int *macro_str
, struct macro_level
**can_read_stream
);
840 void force_charshort_cast(int t
);
841 static void gen_cast(CType
*type
);
843 static Sym
*sym_find(int v
);
844 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
);
847 static int type_size(CType
*type
, int *a
);
848 static inline CType
*pointed_type(CType
*type
);
849 static int pointed_size(CType
*type
);
850 static int lvalue_type(int t
);
851 static int parse_btype(CType
*type
, AttributeDef
*ad
);
852 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
);
853 static int compare_types(CType
*type1
, CType
*type2
, int unqualified
);
854 static int is_compatible_types(CType
*type1
, CType
*type2
);
855 static int is_compatible_parameter_types(CType
*type1
, CType
*type2
);
857 int ieee_finite(double d
);
858 void error(const char *fmt
, ...);
860 void vpushll(long long v
);
863 void lexpand_nr(void);
864 static void vpush_global_sym(CType
*type
, int v
);
865 void vset(CType
*type
, int r
, int v
);
866 void type_to_str(char *buf
, int buf_size
,
867 CType
*type
, const char *varstr
);
868 char *get_tok_str(int v
, CValue
*cv
);
869 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
870 unsigned long offset
, unsigned long size
);
871 static Sym
*external_global_sym(int v
, CType
*type
, int r
);
873 /* section generation */
874 static void section_realloc(Section
*sec
, unsigned long new_size
);
875 static void *section_ptr_add(Section
*sec
, unsigned long size
);
876 static void put_extern_sym(Sym
*sym
, Section
*section
,
877 unsigned long value
, unsigned long size
);
878 static void greloc(Section
*s
, Sym
*sym
, unsigned long addr
, int type
);
879 static int put_elf_str(Section
*s
, const char *sym
);
880 static int put_elf_sym(Section
*s
,
881 unsigned long value
, unsigned long size
,
882 int info
, int other
, int shndx
, const char *name
);
883 static int add_elf_sym(Section
*s
, unsigned long value
, unsigned long size
,
884 int info
, int other
, int sh_num
, const char *name
);
885 static void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
886 int type
, int symbol
);
887 static void put_stabs(const char *str
, int type
, int other
, int desc
,
888 unsigned long value
);
889 static void put_stabs_r(const char *str
, int type
, int other
, int desc
,
890 unsigned long value
, Section
*sec
, int sym_index
);
891 static void put_stabn(int type
, int other
, int desc
, int value
);
892 static void put_stabd(int type
, int other
, int desc
);
893 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
);
895 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
896 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
897 #define AFF_PREPROCESS 0x0004 /* preprocess file */
898 static int tcc_add_file_internal(TCCState
*s
, const char *filename
, int flags
);
901 int tcc_output_coff(TCCState
*s1
, FILE *f
);
904 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
);
905 int pe_load_def_file(struct TCCState
*s1
, int fd
);
906 int pe_test_res_file(void *v
, int size
);
907 int pe_load_res_file(struct TCCState
*s1
, int fd
);
908 void pe_add_runtime(struct TCCState
*s1
);
909 void pe_guess_outfile(char *objfilename
, int output_type
);
910 int pe_output_file(struct TCCState
*s1
, const char *filename
);
914 #ifdef CONFIG_TCC_ASM
916 typedef struct ExprValue
{
921 #define MAX_ASM_OPERANDS 30
923 typedef struct ASMOperand
{
924 int id
; /* GCC 3 optionnal identifier (0 if number only supported */
926 char asm_str
[16]; /* computed asm string for operand */
927 SValue
*vt
; /* C value of the expression */
928 int ref_index
; /* if >= 0, gives reference to a output constraint */
929 int input_index
; /* if >= 0, gives reference to an input constraint */
930 int priority
; /* priority, used to assign registers */
931 int reg
; /* if >= 0, register number used for this operand */
932 int is_llong
; /* true if double register value */
933 int is_memory
; /* true if memory operand */
934 int is_rw
; /* for '+' modifier */
937 static void asm_expr(TCCState
*s1
, ExprValue
*pe
);
938 static int asm_int_expr(TCCState
*s1
);
939 static int find_constraint(ASMOperand
*operands
, int nb_operands
,
940 const char *name
, const char **pp
);
942 static int tcc_assemble(TCCState
*s1
, int do_preprocess
);
946 static void asm_instr(void);
947 static void asm_global_instr(void);
949 /* true if float/double/long double type */
950 static inline int is_float(int t
)
954 return bt
== VT_LDOUBLE
|| bt
== VT_DOUBLE
|| bt
== VT_FLOAT
;
957 #ifdef TCC_TARGET_I386
958 #include "i386-gen.c"
961 #ifdef TCC_TARGET_ARM
965 #ifdef TCC_TARGET_C67
969 #ifdef TCC_TARGET_X86_64
970 #include "x86_64-gen.c"
973 #ifdef CONFIG_TCC_STATIC
975 #define RTLD_LAZY 0x001
976 #define RTLD_NOW 0x002
977 #define RTLD_GLOBAL 0x100
978 #define RTLD_DEFAULT NULL
980 /* dummy function for profiling */
981 void *dlopen(const char *filename
, int flag
)
986 void dlclose(void *p
)
990 const char *dlerror(void)
995 typedef struct TCCSyms
{
1000 #define TCCSYM(a) { #a, &a, },
1002 /* add the symbol you want here if no dynamic linking is done */
1003 static TCCSyms tcc_syms
[] = {
1004 #if !defined(CONFIG_TCCBOOT)
1013 void *resolve_sym(TCCState
*s1
, const char *symbol
, int type
)
1017 while (p
->str
!= NULL
) {
1018 if (!strcmp(p
->str
, symbol
))
1025 #elif !defined(_WIN32)
1029 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
)
1031 return dlsym(RTLD_DEFAULT
, sym
);
1036 /********************************************************/
1038 /* we use our own 'finite' function to avoid potential problems with
1039 non standard math libs */
1040 /* XXX: endianness dependent */
1041 int ieee_finite(double d
)
1044 return ((unsigned)((p
[1] | 0x800fffff) + 1)) >> 31;
1047 /* copy a string and truncate it. */
1048 static char *pstrcpy(char *buf
, int buf_size
, const char *s
)
1055 q_end
= buf
+ buf_size
- 1;
1067 /* strcat and truncate. */
1068 static char *pstrcat(char *buf
, int buf_size
, const char *s
)
1073 pstrcpy(buf
+ len
, buf_size
- len
, s
);
1078 static int strstart(const char *str
, const char *val
, const char **ptr
)
1083 while (*q
!= '\0') {
1096 #define IS_PATHSEP(c) (c == '/' || c == '\\')
1097 #define IS_ABSPATH(p) (IS_PATHSEP(p[0]) || (p[0] && p[1] == ':' && IS_PATHSEP(p[2])))
1098 #define PATHCMP stricmp
1100 #define IS_PATHSEP(c) (c == '/')
1101 #define IS_ABSPATH(p) IS_PATHSEP(p[0])
1102 #define PATHCMP strcmp
1105 /* extract the basename of a file */
1106 static char *tcc_basename(const char *name
)
1108 char *p
= strchr(name
, 0);
1109 while (p
> name
&& !IS_PATHSEP(p
[-1]))
1114 static char *tcc_fileextension (const char *name
)
1116 char *b
= tcc_basename(name
);
1117 char *e
= strrchr(b
, '.');
1118 return e
? e
: strchr(b
, 0);
1122 char *normalize_slashes(char *path
)
1125 for (p
= path
; *p
; ++p
)
1131 void tcc_set_lib_path_w32(TCCState
*s
)
1133 /* on win32, we suppose the lib and includes are at the location
1135 char path
[1024], *p
;
1136 GetModuleFileNameA(NULL
, path
, sizeof path
);
1137 p
= tcc_basename(normalize_slashes(strlwr(path
)));
1138 if (p
- 5 > path
&& 0 == strncmp(p
- 5, "/bin/", 5))
1143 tcc_set_lib_path(s
, path
);
1147 void set_pages_executable(void *ptr
, unsigned long length
)
1150 unsigned long old_protect
;
1151 VirtualProtect(ptr
, length
, PAGE_EXECUTE_READWRITE
, &old_protect
);
1153 unsigned long start
, end
;
1154 start
= (unsigned long)ptr
& ~(PAGESIZE
- 1);
1155 end
= (unsigned long)ptr
+ length
;
1156 end
= (end
+ PAGESIZE
- 1) & ~(PAGESIZE
- 1);
1157 mprotect((void *)start
, end
- start
, PROT_READ
| PROT_WRITE
| PROT_EXEC
);
1161 /* memory management */
1165 unsigned malloc_usable_size(void*);
1168 static inline void tcc_free(void *ptr
)
1171 mem_cur_size
-= malloc_usable_size(ptr
);
1176 static void *tcc_malloc(unsigned long size
)
1181 error("memory full");
1183 mem_cur_size
+= malloc_usable_size(ptr
);
1184 if (mem_cur_size
> mem_max_size
)
1185 mem_max_size
= mem_cur_size
;
1190 static void *tcc_mallocz(unsigned long size
)
1193 ptr
= tcc_malloc(size
);
1194 memset(ptr
, 0, size
);
1198 static inline void *tcc_realloc(void *ptr
, unsigned long size
)
1202 mem_cur_size
-= malloc_usable_size(ptr
);
1204 ptr1
= realloc(ptr
, size
);
1206 /* NOTE: count not correct if alloc error, but not critical */
1207 mem_cur_size
+= malloc_usable_size(ptr1
);
1208 if (mem_cur_size
> mem_max_size
)
1209 mem_max_size
= mem_cur_size
;
1214 static char *tcc_strdup(const char *str
)
1217 ptr
= tcc_malloc(strlen(str
) + 1);
1222 #define free(p) use_tcc_free(p)
1223 #define malloc(s) use_tcc_malloc(s)
1224 #define realloc(p, s) use_tcc_realloc(p, s)
1226 static void dynarray_add(void ***ptab
, int *nb_ptr
, void *data
)
1233 /* every power of two we double array size */
1234 if ((nb
& (nb
- 1)) == 0) {
1239 pp
= tcc_realloc(pp
, nb_alloc
* sizeof(void *));
1241 error("memory full");
1248 static void dynarray_reset(void *pp
, int *n
)
1251 for (p
= *(void***)pp
; *n
; ++p
, --*n
)
1254 tcc_free(*(void**)pp
);
1258 /* symbol allocator */
1259 static Sym
*__sym_malloc(void)
1261 Sym
*sym_pool
, *sym
, *last_sym
;
1264 sym_pool
= tcc_malloc(SYM_POOL_NB
* sizeof(Sym
));
1265 dynarray_add(&sym_pools
, &nb_sym_pools
, sym_pool
);
1267 last_sym
= sym_free_first
;
1269 for(i
= 0; i
< SYM_POOL_NB
; i
++) {
1270 sym
->next
= last_sym
;
1274 sym_free_first
= last_sym
;
1278 static inline Sym
*sym_malloc(void)
1281 sym
= sym_free_first
;
1283 sym
= __sym_malloc();
1284 sym_free_first
= sym
->next
;
1288 static inline void sym_free(Sym
*sym
)
1290 sym
->next
= sym_free_first
;
1291 sym_free_first
= sym
;
1294 Section
*new_section(TCCState
*s1
, const char *name
, int sh_type
, int sh_flags
)
1298 sec
= tcc_mallocz(sizeof(Section
) + strlen(name
));
1299 strcpy(sec
->name
, name
);
1300 sec
->sh_type
= sh_type
;
1301 sec
->sh_flags
= sh_flags
;
1309 sec
->sh_addralign
= 4;
1312 sec
->sh_addralign
= 1;
1315 sec
->sh_addralign
= 32; /* default conservative alignment */
1319 if (sh_flags
& SHF_PRIVATE
) {
1320 dynarray_add((void ***)&s1
->priv_sections
, &s1
->nb_priv_sections
, sec
);
1322 sec
->sh_num
= s1
->nb_sections
;
1323 dynarray_add((void ***)&s1
->sections
, &s1
->nb_sections
, sec
);
1329 static void free_section(Section
*s
)
1334 /* realloc section and set its content to zero */
1335 static void section_realloc(Section
*sec
, unsigned long new_size
)
1338 unsigned char *data
;
1340 size
= sec
->data_allocated
;
1343 while (size
< new_size
)
1345 data
= tcc_realloc(sec
->data
, size
);
1347 error("memory full");
1348 memset(data
+ sec
->data_allocated
, 0, size
- sec
->data_allocated
);
1350 sec
->data_allocated
= size
;
1353 /* reserve at least 'size' bytes in section 'sec' from
1354 sec->data_offset. */
1355 static void *section_ptr_add(Section
*sec
, unsigned long size
)
1357 unsigned long offset
, offset1
;
1359 offset
= sec
->data_offset
;
1360 offset1
= offset
+ size
;
1361 if (offset1
> sec
->data_allocated
)
1362 section_realloc(sec
, offset1
);
1363 sec
->data_offset
= offset1
;
1364 return sec
->data
+ offset
;
1367 /* return a reference to a section, and create it if it does not
1369 Section
*find_section(TCCState
*s1
, const char *name
)
1373 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1374 sec
= s1
->sections
[i
];
1375 if (!strcmp(name
, sec
->name
))
1378 /* sections are created as PROGBITS */
1379 return new_section(s1
, name
, SHT_PROGBITS
, SHF_ALLOC
);
1382 #define SECTION_ABS ((void *)1)
1384 /* update sym->c so that it points to an external symbol in section
1385 'section' with value 'value' */
1386 static void put_extern_sym2(Sym
*sym
, Section
*section
,
1387 unsigned long value
, unsigned long size
,
1388 int can_add_underscore
)
1390 int sym_type
, sym_bind
, sh_num
, info
, other
, attr
;
1395 if (section
== NULL
)
1397 else if (section
== SECTION_ABS
)
1400 sh_num
= section
->sh_num
;
1404 if ((sym
->type
.t
& VT_BTYPE
) == VT_FUNC
) {
1405 sym_type
= STT_FUNC
;
1406 #ifdef TCC_TARGET_PE
1408 attr
= sym
->type
.ref
->r
;
1409 if (FUNC_EXPORT(attr
))
1411 if (FUNC_CALL(attr
) == FUNC_STDCALL
)
1415 sym_type
= STT_OBJECT
;
1418 if (sym
->type
.t
& VT_STATIC
)
1419 sym_bind
= STB_LOCAL
;
1421 sym_bind
= STB_GLOBAL
;
1424 name
= get_tok_str(sym
->v
, NULL
);
1425 #ifdef CONFIG_TCC_BCHECK
1426 if (do_bounds_check
) {
1429 /* XXX: avoid doing that for statics ? */
1430 /* if bound checking is activated, we change some function
1431 names by adding the "__bound" prefix */
1434 /* XXX: we rely only on malloc hooks */
1447 strcpy(buf
, "__bound_");
1455 #ifdef TCC_TARGET_PE
1456 if ((other
& 2) && can_add_underscore
) {
1457 sprintf(buf1
, "_%s@%d", name
, FUNC_ARGS(attr
));
1461 if (tcc_state
->leading_underscore
&& can_add_underscore
) {
1463 pstrcpy(buf1
+ 1, sizeof(buf1
) - 1, name
);
1466 info
= ELFW(ST_INFO
)(sym_bind
, sym_type
);
1467 sym
->c
= add_elf_sym(symtab_section
, value
, size
, info
, other
, sh_num
, name
);
1469 esym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym
->c
];
1470 esym
->st_value
= value
;
1471 esym
->st_size
= size
;
1472 esym
->st_shndx
= sh_num
;
1473 esym
->st_other
|= other
;
1477 static void put_extern_sym(Sym
*sym
, Section
*section
,
1478 unsigned long value
, unsigned long size
)
1480 put_extern_sym2(sym
, section
, value
, size
, 1);
1483 /* add a new relocation entry to symbol 'sym' in section 's' */
1484 static void greloc(Section
*s
, Sym
*sym
, unsigned long offset
, int type
)
1487 put_extern_sym(sym
, NULL
, 0, 0);
1488 /* now we can add ELF relocation info */
1489 put_elf_reloc(symtab_section
, s
, offset
, type
, sym
->c
);
1492 static inline int isid(int c
)
1494 return (c
>= 'a' && c
<= 'z') ||
1495 (c
>= 'A' && c
<= 'Z') ||
1499 static inline int isnum(int c
)
1501 return c
>= '0' && c
<= '9';
1504 static inline int isoct(int c
)
1506 return c
>= '0' && c
<= '7';
1509 static inline int toup(int c
)
1511 if (c
>= 'a' && c
<= 'z')
1512 return c
- 'a' + 'A';
1517 static void strcat_vprintf(char *buf
, int buf_size
, const char *fmt
, va_list ap
)
1521 vsnprintf(buf
+ len
, buf_size
- len
, fmt
, ap
);
1524 static void strcat_printf(char *buf
, int buf_size
, const char *fmt
, ...)
1528 strcat_vprintf(buf
, buf_size
, fmt
, ap
);
1532 void error1(TCCState
*s1
, int is_warning
, const char *fmt
, va_list ap
)
1539 for(f
= s1
->include_stack
; f
< s1
->include_stack_ptr
; f
++)
1540 strcat_printf(buf
, sizeof(buf
), "In file included from %s:%d:\n",
1541 (*f
)->filename
, (*f
)->line_num
);
1542 if (file
->line_num
> 0) {
1543 strcat_printf(buf
, sizeof(buf
),
1544 "%s:%d: ", file
->filename
, file
->line_num
);
1546 strcat_printf(buf
, sizeof(buf
),
1547 "%s: ", file
->filename
);
1550 strcat_printf(buf
, sizeof(buf
),
1554 strcat_printf(buf
, sizeof(buf
), "warning: ");
1555 strcat_vprintf(buf
, sizeof(buf
), fmt
, ap
);
1557 if (!s1
->error_func
) {
1558 /* default case: stderr */
1559 fprintf(stderr
, "%s\n", buf
);
1561 s1
->error_func(s1
->error_opaque
, buf
);
1563 if (!is_warning
|| s1
->warn_error
)
1568 void tcc_set_error_func(TCCState
*s
, void *error_opaque
,
1569 void (*error_func
)(void *opaque
, const char *msg
))
1571 s
->error_opaque
= error_opaque
;
1572 s
->error_func
= error_func
;
1576 /* error without aborting current compilation */
1577 void error_noabort(const char *fmt
, ...)
1579 TCCState
*s1
= tcc_state
;
1583 error1(s1
, 0, fmt
, ap
);
1587 void error(const char *fmt
, ...)
1589 TCCState
*s1
= tcc_state
;
1593 error1(s1
, 0, fmt
, ap
);
1595 /* better than nothing: in some cases, we accept to handle errors */
1596 if (s1
->error_set_jmp_enabled
) {
1597 longjmp(s1
->error_jmp_buf
, 1);
1599 /* XXX: eliminate this someday */
1604 void expect(const char *msg
)
1606 error("%s expected", msg
);
1609 void warning(const char *fmt
, ...)
1611 TCCState
*s1
= tcc_state
;
1618 error1(s1
, 1, fmt
, ap
);
1625 error("'%c' expected", c
);
1629 static void test_lvalue(void)
1631 if (!(vtop
->r
& VT_LVAL
))
1635 /* allocate a new token */
1636 static TokenSym
*tok_alloc_new(TokenSym
**pts
, const char *str
, int len
)
1638 TokenSym
*ts
, **ptable
;
1641 if (tok_ident
>= SYM_FIRST_ANOM
)
1642 error("memory full");
1644 /* expand token table if needed */
1645 i
= tok_ident
- TOK_IDENT
;
1646 if ((i
% TOK_ALLOC_INCR
) == 0) {
1647 ptable
= tcc_realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
1649 error("memory full");
1650 table_ident
= ptable
;
1653 ts
= tcc_malloc(sizeof(TokenSym
) + len
);
1654 table_ident
[i
] = ts
;
1655 ts
->tok
= tok_ident
++;
1656 ts
->sym_define
= NULL
;
1657 ts
->sym_label
= NULL
;
1658 ts
->sym_struct
= NULL
;
1659 ts
->sym_identifier
= NULL
;
1661 ts
->hash_next
= NULL
;
1662 memcpy(ts
->str
, str
, len
);
1663 ts
->str
[len
] = '\0';
1668 #define TOK_HASH_INIT 1
1669 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1671 /* find a token and add it if not found */
1672 static TokenSym
*tok_alloc(const char *str
, int len
)
1674 TokenSym
*ts
, **pts
;
1680 h
= TOK_HASH_FUNC(h
, ((unsigned char *)str
)[i
]);
1681 h
&= (TOK_HASH_SIZE
- 1);
1683 pts
= &hash_ident
[h
];
1688 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
1690 pts
= &(ts
->hash_next
);
1692 return tok_alloc_new(pts
, str
, len
);
1695 /* CString handling */
1697 static void cstr_realloc(CString
*cstr
, int new_size
)
1702 size
= cstr
->size_allocated
;
1704 size
= 8; /* no need to allocate a too small first string */
1705 while (size
< new_size
)
1707 data
= tcc_realloc(cstr
->data_allocated
, size
);
1709 error("memory full");
1710 cstr
->data_allocated
= data
;
1711 cstr
->size_allocated
= size
;
1716 static inline void cstr_ccat(CString
*cstr
, int ch
)
1719 size
= cstr
->size
+ 1;
1720 if (size
> cstr
->size_allocated
)
1721 cstr_realloc(cstr
, size
);
1722 ((unsigned char *)cstr
->data
)[size
- 1] = ch
;
1726 static void cstr_cat(CString
*cstr
, const char *str
)
1738 /* add a wide char */
1739 static void cstr_wccat(CString
*cstr
, int ch
)
1742 size
= cstr
->size
+ sizeof(nwchar_t
);
1743 if (size
> cstr
->size_allocated
)
1744 cstr_realloc(cstr
, size
);
1745 *(nwchar_t
*)(((unsigned char *)cstr
->data
) + size
- sizeof(nwchar_t
)) = ch
;
1749 static void cstr_new(CString
*cstr
)
1751 memset(cstr
, 0, sizeof(CString
));
1754 /* free string and reset it to NULL */
1755 static void cstr_free(CString
*cstr
)
1757 tcc_free(cstr
->data_allocated
);
1761 #define cstr_reset(cstr) cstr_free(cstr)
1763 /* XXX: unicode ? */
1764 static void add_char(CString
*cstr
, int c
)
1766 if (c
== '\'' || c
== '\"' || c
== '\\') {
1767 /* XXX: could be more precise if char or string */
1768 cstr_ccat(cstr
, '\\');
1770 if (c
>= 32 && c
<= 126) {
1773 cstr_ccat(cstr
, '\\');
1775 cstr_ccat(cstr
, 'n');
1777 cstr_ccat(cstr
, '0' + ((c
>> 6) & 7));
1778 cstr_ccat(cstr
, '0' + ((c
>> 3) & 7));
1779 cstr_ccat(cstr
, '0' + (c
& 7));
1784 /* XXX: buffer overflow */
1785 /* XXX: float tokens */
1786 char *get_tok_str(int v
, CValue
*cv
)
1788 static char buf
[STRING_MAX_SIZE
+ 1];
1789 static CString cstr_buf
;
1795 /* NOTE: to go faster, we give a fixed buffer for small strings */
1796 cstr_reset(&cstr_buf
);
1797 cstr_buf
.data
= buf
;
1798 cstr_buf
.size_allocated
= sizeof(buf
);
1804 /* XXX: not quite exact, but only useful for testing */
1805 sprintf(p
, "%u", cv
->ui
);
1809 /* XXX: not quite exact, but only useful for testing */
1810 sprintf(p
, "%Lu", cv
->ull
);
1813 cstr_ccat(&cstr_buf
, 'L');
1815 cstr_ccat(&cstr_buf
, '\'');
1816 add_char(&cstr_buf
, cv
->i
);
1817 cstr_ccat(&cstr_buf
, '\'');
1818 cstr_ccat(&cstr_buf
, '\0');
1822 len
= cstr
->size
- 1;
1824 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1825 cstr_ccat(&cstr_buf
, '\0');
1828 cstr_ccat(&cstr_buf
, 'L');
1831 cstr_ccat(&cstr_buf
, '\"');
1833 len
= cstr
->size
- 1;
1835 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1837 len
= (cstr
->size
/ sizeof(nwchar_t
)) - 1;
1839 add_char(&cstr_buf
, ((nwchar_t
*)cstr
->data
)[i
]);
1841 cstr_ccat(&cstr_buf
, '\"');
1842 cstr_ccat(&cstr_buf
, '\0');
1851 return strcpy(p
, "...");
1853 return strcpy(p
, "<<=");
1855 return strcpy(p
, ">>=");
1857 if (v
< TOK_IDENT
) {
1858 /* search in two bytes table */
1872 } else if (v
< tok_ident
) {
1873 return table_ident
[v
- TOK_IDENT
]->str
;
1874 } else if (v
>= SYM_FIRST_ANOM
) {
1875 /* special name for anonymous symbol */
1876 sprintf(p
, "L.%u", v
- SYM_FIRST_ANOM
);
1878 /* should never happen */
1883 return cstr_buf
.data
;
1886 /* push, without hashing */
1887 static Sym
*sym_push2(Sym
**ps
, int v
, int t
, long c
)
1901 /* find a symbol and return its associated structure. 's' is the top
1902 of the symbol stack */
1903 static Sym
*sym_find2(Sym
*s
, int v
)
1913 /* structure lookup */
1914 static inline Sym
*struct_find(int v
)
1917 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1919 return table_ident
[v
]->sym_struct
;
1922 /* find an identifier */
1923 static inline Sym
*sym_find(int v
)
1926 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1928 return table_ident
[v
]->sym_identifier
;
1931 /* push a given symbol on the symbol stack */
1932 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
)
1941 s
= sym_push2(ps
, v
, type
->t
, c
);
1942 s
->type
.ref
= type
->ref
;
1944 /* don't record fields or anonymous symbols */
1946 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1947 /* record symbol in token array */
1948 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1950 ps
= &ts
->sym_struct
;
1952 ps
= &ts
->sym_identifier
;
1959 /* push a global identifier */
1960 static Sym
*global_identifier_push(int v
, int t
, int c
)
1963 s
= sym_push2(&global_stack
, v
, t
, c
);
1964 /* don't record anonymous symbol */
1965 if (v
< SYM_FIRST_ANOM
) {
1966 ps
= &table_ident
[v
- TOK_IDENT
]->sym_identifier
;
1967 /* modify the top most local identifier, so that
1968 sym_identifier will point to 's' when popped */
1970 ps
= &(*ps
)->prev_tok
;
1977 /* pop symbols until top reaches 'b' */
1978 static void sym_pop(Sym
**ptop
, Sym
*b
)
1988 /* remove symbol in token array */
1990 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1991 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1993 ps
= &ts
->sym_struct
;
1995 ps
= &ts
->sym_identifier
;
2006 BufferedFile
*tcc_open(TCCState
*s1
, const char *filename
)
2011 if (strcmp(filename
, "-") == 0)
2012 fd
= 0, filename
= "stdin";
2014 fd
= open(filename
, O_RDONLY
| O_BINARY
);
2015 if ((verbose
== 2 && fd
>= 0) || verbose
== 3)
2016 printf("%s %*s%s\n", fd
< 0 ? "nf":"->",
2017 (s1
->include_stack_ptr
- s1
->include_stack
), "", filename
);
2020 bf
= tcc_malloc(sizeof(BufferedFile
));
2022 bf
->buf_ptr
= bf
->buffer
;
2023 bf
->buf_end
= bf
->buffer
;
2024 bf
->buffer
[0] = CH_EOB
; /* put eob symbol */
2025 pstrcpy(bf
->filename
, sizeof(bf
->filename
), filename
);
2027 normalize_slashes(bf
->filename
);
2030 bf
->ifndef_macro
= 0;
2031 bf
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
2032 // printf("opening '%s'\n", filename);
2036 void tcc_close(BufferedFile
*bf
)
2038 total_lines
+= bf
->line_num
;
2043 /* fill input buffer and peek next char */
2044 static int tcc_peekc_slow(BufferedFile
*bf
)
2047 /* only tries to read if really end of buffer */
2048 if (bf
->buf_ptr
>= bf
->buf_end
) {
2050 #if defined(PARSE_DEBUG)
2055 len
= read(bf
->fd
, bf
->buffer
, len
);
2062 bf
->buf_ptr
= bf
->buffer
;
2063 bf
->buf_end
= bf
->buffer
+ len
;
2064 *bf
->buf_end
= CH_EOB
;
2066 if (bf
->buf_ptr
< bf
->buf_end
) {
2067 return bf
->buf_ptr
[0];
2069 bf
->buf_ptr
= bf
->buf_end
;
2074 /* return the current character, handling end of block if necessary
2076 static int handle_eob(void)
2078 return tcc_peekc_slow(file
);
2081 /* read next char from current input file and handle end of input buffer */
2082 static inline void inp(void)
2084 ch
= *(++(file
->buf_ptr
));
2085 /* end of buffer/file handling */
2090 /* handle '\[\r]\n' */
2091 static int handle_stray_noerror(void)
2093 while (ch
== '\\') {
2098 } else if (ch
== '\r') {
2112 static void handle_stray(void)
2114 if (handle_stray_noerror())
2115 error("stray '\\' in program");
2118 /* skip the stray and handle the \\n case. Output an error if
2119 incorrect char after the stray */
2120 static int handle_stray1(uint8_t *p
)
2124 if (p
>= file
->buf_end
) {
2141 /* handle just the EOB case, but not stray */
2142 #define PEEKC_EOB(c, p)\
2153 /* handle the complicated stray case */
2154 #define PEEKC(c, p)\
2159 c = handle_stray1(p);\
2164 /* input with '\[\r]\n' handling. Note that this function cannot
2165 handle other characters after '\', so you cannot call it inside
2166 strings or comments */
2167 static void minp(void)
2175 /* single line C++ comments */
2176 static uint8_t *parse_line_comment(uint8_t *p
)
2184 if (c
== '\n' || c
== CH_EOF
) {
2186 } else if (c
== '\\') {
2195 } else if (c
== '\r') {
2213 static uint8_t *parse_comment(uint8_t *p
)
2219 /* fast skip loop */
2222 if (c
== '\n' || c
== '*' || c
== '\\')
2226 if (c
== '\n' || c
== '*' || c
== '\\')
2230 /* now we can handle all the cases */
2234 } else if (c
== '*') {
2240 } else if (c
== '/') {
2241 goto end_of_comment
;
2242 } else if (c
== '\\') {
2247 /* skip '\[\r]\n', otherwise just skip the stray */
2253 } else if (c
== '\r') {
2270 /* stray, eob or eof */
2275 error("unexpected end of file in comment");
2276 } else if (c
== '\\') {
2288 /* space exlcuding newline */
2289 static inline int is_space(int ch
)
2291 return ch
== ' ' || ch
== '\t' || ch
== '\v' || ch
== '\f' || ch
== '\r';
2294 static inline void skip_spaces(void)
2296 while (is_space(ch
))
2300 static inline int check_space(int t
, int *spc
)
2311 /* parse a string without interpreting escapes */
2312 static uint8_t *parse_pp_string(uint8_t *p
,
2313 int sep
, CString
*str
)
2321 } else if (c
== '\\') {
2326 unterminated_string
:
2327 /* XXX: indicate line number of start of string */
2328 error("missing terminating %c character", sep
);
2329 } else if (c
== '\\') {
2330 /* escape : just skip \[\r]\n */
2335 } else if (c
== '\r') {
2338 expect("'\n' after '\r'");
2341 } else if (c
== CH_EOF
) {
2342 goto unterminated_string
;
2345 cstr_ccat(str
, '\\');
2351 } else if (c
== '\n') {
2354 } else if (c
== '\r') {
2358 cstr_ccat(str
, '\r');
2374 /* skip block of text until #else, #elif or #endif. skip also pairs of
2376 void preprocess_skip(void)
2378 int a
, start_of_line
, c
, in_warn_or_error
;
2385 in_warn_or_error
= 0;
2406 } else if (c
== '\\') {
2407 ch
= file
->buf_ptr
[0];
2408 handle_stray_noerror();
2415 if (in_warn_or_error
)
2417 p
= parse_pp_string(p
, c
, NULL
);
2421 if (in_warn_or_error
)
2428 p
= parse_comment(p
);
2429 } else if (ch
== '/') {
2430 p
= parse_line_comment(p
);
2435 if (start_of_line
) {
2440 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
2442 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
2444 else if (tok
== TOK_ENDIF
)
2446 else if( tok
== TOK_ERROR
|| tok
== TOK_WARNING
)
2447 in_warn_or_error
= 1;
2461 /* ParseState handling */
2463 /* XXX: currently, no include file info is stored. Thus, we cannot display
2464 accurate messages if the function or data definition spans multiple
2467 /* save current parse state in 's' */
2468 void save_parse_state(ParseState
*s
)
2470 s
->line_num
= file
->line_num
;
2471 s
->macro_ptr
= macro_ptr
;
2476 /* restore parse state from 's' */
2477 void restore_parse_state(ParseState
*s
)
2479 file
->line_num
= s
->line_num
;
2480 macro_ptr
= s
->macro_ptr
;
2485 /* return the number of additional 'ints' necessary to store the
2487 static inline int tok_ext_size(int t
)
2501 error("unsupported token");
2508 return LDOUBLE_SIZE
/ 4;
2514 /* token string handling */
2516 static inline void tok_str_new(TokenString
*s
)
2520 s
->allocated_len
= 0;
2521 s
->last_line_num
= -1;
2524 static void tok_str_free(int *str
)
2529 static int *tok_str_realloc(TokenString
*s
)
2533 if (s
->allocated_len
== 0) {
2536 len
= s
->allocated_len
* 2;
2538 str
= tcc_realloc(s
->str
, len
* sizeof(int));
2540 error("memory full");
2541 s
->allocated_len
= len
;
2546 static void tok_str_add(TokenString
*s
, int t
)
2552 if (len
>= s
->allocated_len
)
2553 str
= tok_str_realloc(s
);
2558 static void tok_str_add2(TokenString
*s
, int t
, CValue
*cv
)
2565 /* allocate space for worst case */
2566 if (len
+ TOK_MAX_SIZE
> s
->allocated_len
)
2567 str
= tok_str_realloc(s
);
2576 str
[len
++] = cv
->tab
[0];
2585 nb_words
= (sizeof(CString
) + cv
->cstr
->size
+ 3) >> 2;
2586 while ((len
+ nb_words
) > s
->allocated_len
)
2587 str
= tok_str_realloc(s
);
2588 cstr
= (CString
*)(str
+ len
);
2590 cstr
->size
= cv
->cstr
->size
;
2591 cstr
->data_allocated
= NULL
;
2592 cstr
->size_allocated
= cstr
->size
;
2593 memcpy((char *)cstr
+ sizeof(CString
),
2594 cv
->cstr
->data
, cstr
->size
);
2601 #if LDOUBLE_SIZE == 8
2604 str
[len
++] = cv
->tab
[0];
2605 str
[len
++] = cv
->tab
[1];
2607 #if LDOUBLE_SIZE == 12
2609 str
[len
++] = cv
->tab
[0];
2610 str
[len
++] = cv
->tab
[1];
2611 str
[len
++] = cv
->tab
[2];
2612 #elif LDOUBLE_SIZE == 16
2614 str
[len
++] = cv
->tab
[0];
2615 str
[len
++] = cv
->tab
[1];
2616 str
[len
++] = cv
->tab
[2];
2617 str
[len
++] = cv
->tab
[3];
2618 #elif LDOUBLE_SIZE != 8
2619 #error add long double size support
2628 /* add the current parse token in token string 's' */
2629 static void tok_str_add_tok(TokenString
*s
)
2633 /* save line number info */
2634 if (file
->line_num
!= s
->last_line_num
) {
2635 s
->last_line_num
= file
->line_num
;
2636 cval
.i
= s
->last_line_num
;
2637 tok_str_add2(s
, TOK_LINENUM
, &cval
);
2639 tok_str_add2(s
, tok
, &tokc
);
2642 #if LDOUBLE_SIZE == 16
2643 #define LDOUBLE_GET(p, cv) \
2648 #elif LDOUBLE_SIZE == 12
2649 #define LDOUBLE_GET(p, cv) \
2653 #elif LDOUBLE_SIZE == 8
2654 #define LDOUBLE_GET(p, cv) \
2658 #error add long double size support
2662 /* get a token from an integer array and increment pointer
2663 accordingly. we code it as a macro to avoid pointer aliasing. */
2664 #define TOK_GET(t, p, cv) \
2679 cv.cstr = (CString *)p; \
2680 cv.cstr->data = (char *)p + sizeof(CString);\
2681 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2690 case TOK_CLDOUBLE: \
2691 LDOUBLE_GET(p, cv); \
2692 p += LDOUBLE_SIZE / 4; \
2699 /* defines handling */
2700 static inline void define_push(int v
, int macro_type
, int *str
, Sym
*first_arg
)
2704 s
= sym_push2(&define_stack
, v
, macro_type
, (long)str
);
2705 s
->next
= first_arg
;
2706 table_ident
[v
- TOK_IDENT
]->sym_define
= s
;
2709 /* undefined a define symbol. Its name is just set to zero */
2710 static void define_undef(Sym
*s
)
2714 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2715 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2719 static inline Sym
*define_find(int v
)
2722 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2724 return table_ident
[v
]->sym_define
;
2727 /* free define stack until top reaches 'b' */
2728 static void free_defines(Sym
*b
)
2736 /* do not free args or predefined defines */
2738 tok_str_free((int *)top
->c
);
2740 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2741 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2749 static Sym
*label_find(int v
)
2752 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2754 return table_ident
[v
]->sym_label
;
2757 static Sym
*label_push(Sym
**ptop
, int v
, int flags
)
2760 s
= sym_push2(ptop
, v
, 0, 0);
2762 ps
= &table_ident
[v
- TOK_IDENT
]->sym_label
;
2763 if (ptop
== &global_label_stack
) {
2764 /* modify the top most local identifier, so that
2765 sym_identifier will point to 's' when popped */
2767 ps
= &(*ps
)->prev_tok
;
2774 /* pop labels until element last is reached. Look if any labels are
2775 undefined. Define symbols if '&&label' was used. */
2776 static void label_pop(Sym
**ptop
, Sym
*slast
)
2779 for(s
= *ptop
; s
!= slast
; s
= s1
) {
2781 if (s
->r
== LABEL_DECLARED
) {
2782 warning("label '%s' declared but not used", get_tok_str(s
->v
, NULL
));
2783 } else if (s
->r
== LABEL_FORWARD
) {
2784 error("label '%s' used but not defined",
2785 get_tok_str(s
->v
, NULL
));
2788 /* define corresponding symbol. A size of
2790 put_extern_sym(s
, cur_text_section
, (long)s
->next
, 1);
2794 table_ident
[s
->v
- TOK_IDENT
]->sym_label
= s
->prev_tok
;
2800 /* eval an expression for #if/#elif */
2801 static int expr_preprocess(void)
2807 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2808 next(); /* do macro subst */
2809 if (tok
== TOK_DEFINED
) {
2814 c
= define_find(tok
) != 0;
2819 } else if (tok
>= TOK_IDENT
) {
2820 /* if undefined macro */
2824 tok_str_add_tok(&str
);
2826 tok_str_add(&str
, -1); /* simulate end of file */
2827 tok_str_add(&str
, 0);
2828 /* now evaluate C constant expression */
2829 macro_ptr
= str
.str
;
2833 tok_str_free(str
.str
);
2837 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2838 static void tok_print(int *str
)
2845 TOK_GET(t
, str
, cval
);
2848 printf("%s", get_tok_str(t
, &cval
));
2854 /* parse after #define */
2855 static void parse_define(void)
2857 Sym
*s
, *first
, **ps
;
2858 int v
, t
, varg
, is_vaargs
, spc
;
2863 error("invalid macro name '%s'", get_tok_str(tok
, &tokc
));
2864 /* XXX: should check if same macro (ANSI) */
2867 /* '(' must be just after macro definition for MACRO_FUNC */
2872 while (tok
!= ')') {
2876 if (varg
== TOK_DOTS
) {
2877 varg
= TOK___VA_ARGS__
;
2879 } else if (tok
== TOK_DOTS
&& gnu_ext
) {
2883 if (varg
< TOK_IDENT
)
2884 error("badly punctuated parameter list");
2885 s
= sym_push2(&define_stack
, varg
| SYM_FIELD
, is_vaargs
, 0);
2898 /* EOF testing necessary for '-D' handling */
2899 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2900 /* remove spaces around ## and after '#' */
2901 if (TOK_TWOSHARPS
== tok
) {
2905 } else if ('#' == tok
) {
2907 } else if (check_space(tok
, &spc
)) {
2910 tok_str_add2(&str
, tok
, &tokc
);
2915 --str
.len
; /* remove trailing space */
2916 tok_str_add(&str
, 0);
2918 printf("define %s %d: ", get_tok_str(v
, NULL
), t
);
2921 define_push(v
, t
, str
.str
, first
);
2924 static inline int hash_cached_include(int type
, const char *filename
)
2926 const unsigned char *s
;
2930 h
= TOK_HASH_FUNC(h
, type
);
2933 h
= TOK_HASH_FUNC(h
, *s
);
2936 h
&= (CACHED_INCLUDES_HASH_SIZE
- 1);
2940 /* XXX: use a token or a hash table to accelerate matching ? */
2941 static CachedInclude
*search_cached_include(TCCState
*s1
,
2942 int type
, const char *filename
)
2946 h
= hash_cached_include(type
, filename
);
2947 i
= s1
->cached_includes_hash
[h
];
2951 e
= s1
->cached_includes
[i
- 1];
2952 if (e
->type
== type
&& !PATHCMP(e
->filename
, filename
))
2959 static inline void add_cached_include(TCCState
*s1
, int type
,
2960 const char *filename
, int ifndef_macro
)
2965 if (search_cached_include(s1
, type
, filename
))
2968 printf("adding cached '%s' %s\n", filename
, get_tok_str(ifndef_macro
, NULL
));
2970 e
= tcc_malloc(sizeof(CachedInclude
) + strlen(filename
));
2974 strcpy(e
->filename
, filename
);
2975 e
->ifndef_macro
= ifndef_macro
;
2976 dynarray_add((void ***)&s1
->cached_includes
, &s1
->nb_cached_includes
, e
);
2977 /* add in hash table */
2978 h
= hash_cached_include(type
, filename
);
2979 e
->hash_next
= s1
->cached_includes_hash
[h
];
2980 s1
->cached_includes_hash
[h
] = s1
->nb_cached_includes
;
2983 static void pragma_parse(TCCState
*s1
)
2988 if (tok
== TOK_pack
) {
2991 #pragma pack(1) // set
2992 #pragma pack() // reset to default
2993 #pragma pack(push,1) // push & set
2994 #pragma pack(pop) // restore previous
2998 if (tok
== TOK_ASM_pop
) {
3000 if (s1
->pack_stack_ptr
<= s1
->pack_stack
) {
3002 error("out of pack stack");
3004 s1
->pack_stack_ptr
--;
3008 if (tok
== TOK_ASM_push
) {
3010 if (s1
->pack_stack_ptr
>= s1
->pack_stack
+ PACK_STACK_SIZE
- 1)
3012 s1
->pack_stack_ptr
++;
3015 if (tok
!= TOK_CINT
) {
3017 error("invalid pack pragma");
3020 if (val
< 1 || val
> 16 || (val
& (val
- 1)) != 0)
3024 *s1
->pack_stack_ptr
= val
;
3030 /* is_bof is true if first non space token at beginning of file */
3031 static void preprocess(int is_bof
)
3033 TCCState
*s1
= tcc_state
;
3034 int size
, i
, c
, n
, saved_parse_flags
;
3041 saved_parse_flags
= parse_flags
;
3042 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
|
3043 PARSE_FLAG_LINEFEED
;
3053 s
= define_find(tok
);
3054 /* undefine symbol by putting an invalid name */
3059 case TOK_INCLUDE_NEXT
:
3060 ch
= file
->buf_ptr
[0];
3061 /* XXX: incorrect if comments : use next_nomacro with a special mode */
3066 } else if (ch
== '\"') {
3071 while (ch
!= c
&& ch
!= '\n' && ch
!= CH_EOF
) {
3072 if ((q
- buf
) < sizeof(buf
) - 1)
3075 if (handle_stray_noerror() == 0)
3083 /* eat all spaces and comments after include */
3084 /* XXX: slightly incorrect */
3085 while (ch1
!= '\n' && ch1
!= CH_EOF
)
3089 /* computed #include : either we have only strings or
3090 we have anything enclosed in '<>' */
3093 if (tok
== TOK_STR
) {
3094 while (tok
!= TOK_LINEFEED
) {
3095 if (tok
!= TOK_STR
) {
3097 error("'#include' expects \"FILENAME\" or <FILENAME>");
3099 pstrcat(buf
, sizeof(buf
), (char *)tokc
.cstr
->data
);
3105 while (tok
!= TOK_LINEFEED
) {
3106 pstrcat(buf
, sizeof(buf
), get_tok_str(tok
, &tokc
));
3110 /* check syntax and remove '<>' */
3111 if (len
< 2 || buf
[0] != '<' || buf
[len
- 1] != '>')
3112 goto include_syntax
;
3113 memmove(buf
, buf
+ 1, len
- 2);
3114 buf
[len
- 2] = '\0';
3119 e
= search_cached_include(s1
, c
, buf
);
3120 if (e
&& define_find(e
->ifndef_macro
)) {
3121 /* no need to parse the include because the 'ifndef macro'
3124 printf("%s: skipping %s\n", file
->filename
, buf
);
3127 if (s1
->include_stack_ptr
>= s1
->include_stack
+ INCLUDE_STACK_SIZE
)
3128 error("#include recursion too deep");
3129 /* push current file in stack */
3130 /* XXX: fix current line init */
3131 *s1
->include_stack_ptr
++ = file
;
3133 /* check absolute include path */
3134 if (IS_ABSPATH(buf
)) {
3135 f
= tcc_open(s1
, buf
);
3140 /* first search in current dir if "header.h" */
3141 size
= tcc_basename(file
->filename
) - file
->filename
;
3142 if (size
> sizeof(buf1
) - 1)
3143 size
= sizeof(buf1
) - 1;
3144 memcpy(buf1
, file
->filename
, size
);
3146 pstrcat(buf1
, sizeof(buf1
), buf
);
3147 f
= tcc_open(s1
, buf1
);
3149 if (tok
== TOK_INCLUDE_NEXT
)
3155 /* now search in all the include paths */
3156 n
= s1
->nb_include_paths
+ s1
->nb_sysinclude_paths
;
3157 for(i
= 0; i
< n
; i
++) {
3159 if (i
< s1
->nb_include_paths
)
3160 path
= s1
->include_paths
[i
];
3162 path
= s1
->sysinclude_paths
[i
- s1
->nb_include_paths
];
3163 pstrcpy(buf1
, sizeof(buf1
), path
);
3164 pstrcat(buf1
, sizeof(buf1
), "/");
3165 pstrcat(buf1
, sizeof(buf1
), buf
);
3166 f
= tcc_open(s1
, buf1
);
3168 if (tok
== TOK_INCLUDE_NEXT
)
3174 --s1
->include_stack_ptr
;
3175 error("include file '%s' not found", buf
);
3179 printf("%s: including %s\n", file
->filename
, buf1
);
3182 pstrcpy(f
->inc_filename
, sizeof(f
->inc_filename
), buf
);
3184 /* add include file debug info */
3186 put_stabs(file
->filename
, N_BINCL
, 0, 0, 0);
3188 tok_flags
|= TOK_FLAG_BOF
| TOK_FLAG_BOL
;
3189 ch
= file
->buf_ptr
[0];
3197 c
= expr_preprocess();
3203 if (tok
< TOK_IDENT
)
3204 error("invalid argument for '#if%sdef'", c
? "n" : "");
3208 printf("#ifndef %s\n", get_tok_str(tok
, NULL
));
3210 file
->ifndef_macro
= tok
;
3213 c
= (define_find(tok
) != 0) ^ c
;
3215 if (s1
->ifdef_stack_ptr
>= s1
->ifdef_stack
+ IFDEF_STACK_SIZE
)
3216 error("memory full");
3217 *s1
->ifdef_stack_ptr
++ = c
;
3220 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
3221 error("#else without matching #if");
3222 if (s1
->ifdef_stack_ptr
[-1] & 2)
3223 error("#else after #else");
3224 c
= (s1
->ifdef_stack_ptr
[-1] ^= 3);
3227 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
3228 error("#elif without matching #if");
3229 c
= s1
->ifdef_stack_ptr
[-1];
3231 error("#elif after #else");
3232 /* last #if/#elif expression was true: we skip */
3235 c
= expr_preprocess();
3236 s1
->ifdef_stack_ptr
[-1] = c
;
3246 if (s1
->ifdef_stack_ptr
<= file
->ifdef_stack_ptr
)
3247 error("#endif without matching #if");
3248 s1
->ifdef_stack_ptr
--;
3249 /* '#ifndef macro' was at the start of file. Now we check if
3250 an '#endif' is exactly at the end of file */
3251 if (file
->ifndef_macro
&&
3252 s1
->ifdef_stack_ptr
== file
->ifdef_stack_ptr
) {
3253 file
->ifndef_macro_saved
= file
->ifndef_macro
;
3254 /* need to set to zero to avoid false matches if another
3255 #ifndef at middle of file */
3256 file
->ifndef_macro
= 0;
3257 while (tok
!= TOK_LINEFEED
)
3259 tok_flags
|= TOK_FLAG_ENDIF
;
3265 if (tok
!= TOK_CINT
)
3267 file
->line_num
= tokc
.i
- 1; /* the line number will be incremented after */
3269 if (tok
!= TOK_LINEFEED
) {
3272 pstrcpy(file
->filename
, sizeof(file
->filename
),
3273 (char *)tokc
.cstr
->data
);
3279 ch
= file
->buf_ptr
[0];
3282 while (ch
!= '\n' && ch
!= CH_EOF
) {
3283 if ((q
- buf
) < sizeof(buf
) - 1)
3286 if (handle_stray_noerror() == 0)
3293 error("#error %s", buf
);
3295 warning("#warning %s", buf
);
3301 if (tok
== TOK_LINEFEED
|| tok
== '!' || tok
== TOK_CINT
) {
3302 /* '!' is ignored to allow C scripts. numbers are ignored
3303 to emulate cpp behaviour */
3305 if (!(saved_parse_flags
& PARSE_FLAG_ASM_COMMENTS
))
3306 warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok
, &tokc
));
3310 /* ignore other preprocess commands or #! for C scripts */
3311 while (tok
!= TOK_LINEFEED
)
3314 parse_flags
= saved_parse_flags
;
3317 /* evaluate escape codes in a string. */
3318 static void parse_escape_string(CString
*outstr
, const uint8_t *buf
, int is_long
)
3333 case '0': case '1': case '2': case '3':
3334 case '4': case '5': case '6': case '7':
3335 /* at most three octal digits */
3340 n
= n
* 8 + c
- '0';
3344 n
= n
* 8 + c
- '0';
3349 goto add_char_nonext
;
3357 if (c
>= 'a' && c
<= 'f')
3359 else if (c
>= 'A' && c
<= 'F')
3369 goto add_char_nonext
;
3393 goto invalid_escape
;
3403 if (c
>= '!' && c
<= '~')
3404 warning("unknown escape sequence: \'\\%c\'", c
);
3406 warning("unknown escape sequence: \'\\x%x\'", c
);
3413 cstr_ccat(outstr
, c
);
3415 cstr_wccat(outstr
, c
);
3417 /* add a trailing '\0' */
3419 cstr_ccat(outstr
, '\0');
3421 cstr_wccat(outstr
, '\0');
3424 /* we use 64 bit numbers */
3427 /* bn = (bn << shift) | or_val */
3428 void bn_lshift(unsigned int *bn
, int shift
, int or_val
)
3432 for(i
=0;i
<BN_SIZE
;i
++) {
3434 bn
[i
] = (v
<< shift
) | or_val
;
3435 or_val
= v
>> (32 - shift
);
3439 void bn_zero(unsigned int *bn
)
3442 for(i
=0;i
<BN_SIZE
;i
++) {
3447 /* parse number in null terminated string 'p' and return it in the
3449 void parse_number(const char *p
)
3451 int b
, t
, shift
, frac_bits
, s
, exp_val
, ch
;
3453 unsigned int bn
[BN_SIZE
];
3464 goto float_frac_parse
;
3465 } else if (t
== '0') {
3466 if (ch
== 'x' || ch
== 'X') {
3470 } else if (tcc_ext
&& (ch
== 'b' || ch
== 'B')) {
3476 /* parse all digits. cannot check octal numbers at this stage
3477 because of floating point constants */
3479 if (ch
>= 'a' && ch
<= 'f')
3481 else if (ch
>= 'A' && ch
<= 'F')
3489 if (q
>= token_buf
+ STRING_MAX_SIZE
) {
3491 error("number too long");
3497 ((ch
== 'e' || ch
== 'E') && b
== 10) ||
3498 ((ch
== 'p' || ch
== 'P') && (b
== 16 || b
== 2))) {
3500 /* NOTE: strtox should support that for hexa numbers, but
3501 non ISOC99 libcs do not support it, so we prefer to do
3503 /* hexadecimal or binary floats */
3504 /* XXX: handle overflows */
3516 } else if (t
>= 'a') {
3518 } else if (t
>= 'A') {
3523 bn_lshift(bn
, shift
, t
);
3530 if (t
>= 'a' && t
<= 'f') {
3532 } else if (t
>= 'A' && t
<= 'F') {
3534 } else if (t
>= '0' && t
<= '9') {
3540 error("invalid digit");
3541 bn_lshift(bn
, shift
, t
);
3546 if (ch
!= 'p' && ch
!= 'P')
3553 } else if (ch
== '-') {
3557 if (ch
< '0' || ch
> '9')
3558 expect("exponent digits");
3559 while (ch
>= '0' && ch
<= '9') {
3560 exp_val
= exp_val
* 10 + ch
- '0';
3563 exp_val
= exp_val
* s
;
3565 /* now we can generate the number */
3566 /* XXX: should patch directly float number */
3567 d
= (double)bn
[1] * 4294967296.0 + (double)bn
[0];
3568 d
= ldexp(d
, exp_val
- frac_bits
);
3573 /* float : should handle overflow */
3575 } else if (t
== 'L') {
3578 /* XXX: not large enough */
3579 tokc
.ld
= (long double)d
;
3585 /* decimal floats */
3587 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3592 while (ch
>= '0' && ch
<= '9') {
3593 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3599 if (ch
== 'e' || ch
== 'E') {
3600 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3604 if (ch
== '-' || ch
== '+') {
3605 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3610 if (ch
< '0' || ch
> '9')
3611 expect("exponent digits");
3612 while (ch
>= '0' && ch
<= '9') {
3613 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3625 tokc
.f
= strtof(token_buf
, NULL
);
3626 } else if (t
== 'L') {
3629 tokc
.ld
= strtold(token_buf
, NULL
);
3632 tokc
.d
= strtod(token_buf
, NULL
);
3636 unsigned long long n
, n1
;
3639 /* integer number */
3642 if (b
== 10 && *q
== '0') {
3649 /* no need for checks except for base 10 / 8 errors */
3652 } else if (t
>= 'a') {
3654 } else if (t
>= 'A') {
3659 error("invalid digit");
3663 /* detect overflow */
3664 /* XXX: this test is not reliable */
3666 error("integer constant overflow");
3669 /* XXX: not exactly ANSI compliant */
3670 if ((n
& 0xffffffff00000000LL
) != 0) {
3675 } else if (n
> 0x7fffffff) {
3686 error("three 'l's in integer constant");
3689 if (tok
== TOK_CINT
)
3691 else if (tok
== TOK_CUINT
)
3695 } else if (t
== 'U') {
3697 error("two 'u's in integer constant");
3699 if (tok
== TOK_CINT
)
3701 else if (tok
== TOK_CLLONG
)
3708 if (tok
== TOK_CINT
|| tok
== TOK_CUINT
)
3714 error("invalid number\n");
3718 #define PARSE2(c1, tok1, c2, tok2) \
3729 /* return next token without macro substitution */
3730 static inline void next_nomacro1(void)
3745 goto keep_tok_flags
;
3752 /* first look if it is in fact an end of buffer */
3753 if (p
>= file
->buf_end
) {
3757 if (p
>= file
->buf_end
)
3770 TCCState
*s1
= tcc_state
;
3771 if ((parse_flags
& PARSE_FLAG_LINEFEED
)
3772 && !(tok_flags
& TOK_FLAG_EOF
)) {
3773 tok_flags
|= TOK_FLAG_EOF
;
3775 goto keep_tok_flags
;
3776 } else if (s1
->include_stack_ptr
== s1
->include_stack
||
3777 !(parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3778 /* no include left : end of file. */
3781 tok_flags
&= ~TOK_FLAG_EOF
;
3782 /* pop include file */
3784 /* test if previous '#endif' was after a #ifdef at
3786 if (tok_flags
& TOK_FLAG_ENDIF
) {
3788 printf("#endif %s\n", get_tok_str(file
->ifndef_macro_saved
, NULL
));
3790 add_cached_include(s1
, file
->inc_type
, file
->inc_filename
,
3791 file
->ifndef_macro_saved
);
3794 /* add end of include file debug info */
3796 put_stabd(N_EINCL
, 0, 0);
3798 /* pop include stack */
3800 s1
->include_stack_ptr
--;
3801 file
= *s1
->include_stack_ptr
;
3810 tok_flags
|= TOK_FLAG_BOL
;
3812 if (0 == (parse_flags
& PARSE_FLAG_LINEFEED
))
3815 goto keep_tok_flags
;
3820 if ((tok_flags
& TOK_FLAG_BOL
) &&
3821 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3823 preprocess(tok_flags
& TOK_FLAG_BOF
);
3829 tok
= TOK_TWOSHARPS
;
3831 if (parse_flags
& PARSE_FLAG_ASM_COMMENTS
) {
3832 p
= parse_line_comment(p
- 1);
3841 case 'a': case 'b': case 'c': case 'd':
3842 case 'e': case 'f': case 'g': case 'h':
3843 case 'i': case 'j': case 'k': case 'l':
3844 case 'm': case 'n': case 'o': case 'p':
3845 case 'q': case 'r': case 's': case 't':
3846 case 'u': case 'v': case 'w': case 'x':
3848 case 'A': case 'B': case 'C': case 'D':
3849 case 'E': case 'F': case 'G': case 'H':
3850 case 'I': case 'J': case 'K':
3851 case 'M': case 'N': case 'O': case 'P':
3852 case 'Q': case 'R': case 'S': case 'T':
3853 case 'U': case 'V': case 'W': case 'X':
3859 h
= TOK_HASH_FUNC(h
, c
);
3863 if (!isidnum_table
[c
-CH_EOF
])
3865 h
= TOK_HASH_FUNC(h
, c
);
3872 /* fast case : no stray found, so we have the full token
3873 and we have already hashed it */
3875 h
&= (TOK_HASH_SIZE
- 1);
3876 pts
= &hash_ident
[h
];
3881 if (ts
->len
== len
&& !memcmp(ts
->str
, p1
, len
))
3883 pts
= &(ts
->hash_next
);
3885 ts
= tok_alloc_new(pts
, p1
, len
);
3889 cstr_reset(&tokcstr
);
3892 cstr_ccat(&tokcstr
, *p1
);
3898 while (isidnum_table
[c
-CH_EOF
]) {
3899 cstr_ccat(&tokcstr
, c
);
3902 ts
= tok_alloc(tokcstr
.data
, tokcstr
.size
);
3908 if (t
!= '\\' && t
!= '\'' && t
!= '\"') {
3910 goto parse_ident_fast
;
3913 if (c
== '\'' || c
== '\"') {
3917 cstr_reset(&tokcstr
);
3918 cstr_ccat(&tokcstr
, 'L');
3919 goto parse_ident_slow
;
3923 case '0': case '1': case '2': case '3':
3924 case '4': case '5': case '6': case '7':
3927 cstr_reset(&tokcstr
);
3928 /* after the first digit, accept digits, alpha, '.' or sign if
3929 prefixed by 'eEpP' */
3933 cstr_ccat(&tokcstr
, c
);
3935 if (!(isnum(c
) || isid(c
) || c
== '.' ||
3936 ((c
== '+' || c
== '-') &&
3937 (t
== 'e' || t
== 'E' || t
== 'p' || t
== 'P'))))
3940 /* We add a trailing '\0' to ease parsing */
3941 cstr_ccat(&tokcstr
, '\0');
3942 tokc
.cstr
= &tokcstr
;
3946 /* special dot handling because it can also start a number */
3949 cstr_reset(&tokcstr
);
3950 cstr_ccat(&tokcstr
, '.');
3952 } else if (c
== '.') {
3972 /* parse the string */
3974 p
= parse_pp_string(p
, sep
, &str
);
3975 cstr_ccat(&str
, '\0');
3977 /* eval the escape (should be done as TOK_PPNUM) */
3978 cstr_reset(&tokcstr
);
3979 parse_escape_string(&tokcstr
, str
.data
, is_long
);
3984 /* XXX: make it portable */
3988 char_size
= sizeof(nwchar_t
);
3989 if (tokcstr
.size
<= char_size
)
3990 error("empty character constant");
3991 if (tokcstr
.size
> 2 * char_size
)
3992 warning("multi-character character constant");
3994 tokc
.i
= *(int8_t *)tokcstr
.data
;
3997 tokc
.i
= *(nwchar_t
*)tokcstr
.data
;
4001 tokc
.cstr
= &tokcstr
;
4015 } else if (c
== '<') {
4033 } else if (c
== '>') {
4051 } else if (c
== '=') {
4064 } else if (c
== '=') {
4077 } else if (c
== '=') {
4090 } else if (c
== '=') {
4093 } else if (c
== '>') {
4101 PARSE2('!', '!', '=', TOK_NE
)
4102 PARSE2('=', '=', '=', TOK_EQ
)
4103 PARSE2('*', '*', '=', TOK_A_MUL
)
4104 PARSE2('%', '%', '=', TOK_A_MOD
)
4105 PARSE2('^', '^', '=', TOK_A_XOR
)
4107 /* comments or operator */
4111 p
= parse_comment(p
);
4113 } else if (c
== '/') {
4114 p
= parse_line_comment(p
);
4116 } else if (c
== '=') {
4136 case '$': /* only used in assembler */
4137 case '@': /* dito */
4142 error("unrecognized character \\x%02x", c
);
4148 #if defined(PARSE_DEBUG)
4149 printf("token = %s\n", get_tok_str(tok
, &tokc
));
4153 /* return next token without macro substitution. Can read input from
4155 static void next_nomacro_spc(void)
4161 TOK_GET(tok
, macro_ptr
, tokc
);
4162 if (tok
== TOK_LINENUM
) {
4163 file
->line_num
= tokc
.i
;
4172 static void next_nomacro(void)
4176 } while (is_space(tok
));
4179 /* substitute args in macro_str and return allocated string */
4180 static int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
4182 int *st
, last_tok
, t
, spc
;
4191 TOK_GET(t
, macro_str
, cval
);
4196 TOK_GET(t
, macro_str
, cval
);
4199 s
= sym_find2(args
, t
);
4205 TOK_GET(t
, st
, cval
);
4206 if (!check_space(t
, &spc
))
4207 cstr_cat(&cstr
, get_tok_str(t
, &cval
));
4210 cstr_ccat(&cstr
, '\0');
4212 printf("stringize: %s\n", (char *)cstr
.data
);
4216 tok_str_add2(&str
, TOK_STR
, &cval
);
4219 tok_str_add2(&str
, t
, &cval
);
4221 } else if (t
>= TOK_IDENT
) {
4222 s
= sym_find2(args
, t
);
4225 /* if '##' is present before or after, no arg substitution */
4226 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
4227 /* special case for var arg macros : ## eats the
4228 ',' if empty VA_ARGS variable. */
4229 /* XXX: test of the ',' is not 100%
4230 reliable. should fix it to avoid security
4232 if (gnu_ext
&& s
->type
.t
&&
4233 last_tok
== TOK_TWOSHARPS
&&
4234 str
.len
>= 2 && str
.str
[str
.len
- 2] == ',') {
4236 /* suppress ',' '##' */
4239 /* suppress '##' and add variable */
4247 TOK_GET(t1
, st
, cval
);
4250 tok_str_add2(&str
, t1
, &cval
);
4254 /* NOTE: the stream cannot be read when macro
4255 substituing an argument */
4256 macro_subst(&str
, nested_list
, st
, NULL
);
4259 tok_str_add(&str
, t
);
4262 tok_str_add2(&str
, t
, &cval
);
4266 tok_str_add(&str
, 0);
4270 static char const ab_month_name
[12][4] =
4272 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4273 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4276 /* do macro substitution of current token with macro 's' and add
4277 result to (tok_str,tok_len). 'nested_list' is the list of all
4278 macros we got inside to avoid recursing. Return non zero if no
4279 substitution needs to be done */
4280 static int macro_subst_tok(TokenString
*tok_str
,
4281 Sym
**nested_list
, Sym
*s
, struct macro_level
**can_read_stream
)
4283 Sym
*args
, *sa
, *sa1
;
4284 int mstr_allocated
, parlevel
, *mstr
, t
, t1
, *p
, spc
;
4291 /* if symbol is a macro, prepare substitution */
4292 /* special macros */
4293 if (tok
== TOK___LINE__
) {
4294 snprintf(buf
, sizeof(buf
), "%d", file
->line_num
);
4298 } else if (tok
== TOK___FILE__
) {
4299 cstrval
= file
->filename
;
4301 } else if (tok
== TOK___DATE__
|| tok
== TOK___TIME__
) {
4306 tm
= localtime(&ti
);
4307 if (tok
== TOK___DATE__
) {
4308 snprintf(buf
, sizeof(buf
), "%s %2d %d",
4309 ab_month_name
[tm
->tm_mon
], tm
->tm_mday
, tm
->tm_year
+ 1900);
4311 snprintf(buf
, sizeof(buf
), "%02d:%02d:%02d",
4312 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
);
4319 cstr_cat(&cstr
, cstrval
);
4320 cstr_ccat(&cstr
, '\0');
4322 tok_str_add2(tok_str
, t1
, &cval
);
4327 if (s
->type
.t
== MACRO_FUNC
) {
4328 /* NOTE: we do not use next_nomacro to avoid eating the
4329 next token. XXX: find better solution */
4333 while (is_space(t
= *p
) || TOK_LINEFEED
== t
)
4335 if (t
== 0 && can_read_stream
) {
4336 /* end of macro stream: we must look at the token
4337 after in the file */
4338 struct macro_level
*ml
= *can_read_stream
;
4344 *can_read_stream
= ml
-> prev
;
4349 /* XXX: incorrect with comments */
4350 ch
= file
->buf_ptr
[0];
4351 while (is_space(ch
) || ch
== '\n')
4355 if (t
!= '(') /* no macro subst */
4358 /* argument macro */
4363 /* NOTE: empty args are allowed, except if no args */
4365 /* handle '()' case */
4366 if (!args
&& !sa
&& tok
== ')')
4369 error("macro '%s' used with too many args",
4370 get_tok_str(s
->v
, 0));
4373 /* NOTE: non zero sa->t indicates VA_ARGS */
4374 while ((parlevel
> 0 ||
4376 (tok
!= ',' || sa
->type
.t
))) &&
4380 else if (tok
== ')')
4382 if (tok
== TOK_LINEFEED
)
4384 if (!check_space(tok
, &spc
))
4385 tok_str_add2(&str
, tok
, &tokc
);
4389 tok_str_add(&str
, 0);
4390 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, sa
->type
.t
, (long)str
.str
);
4393 /* special case for gcc var args: add an empty
4394 var arg argument if it is omitted */
4395 if (sa
&& sa
->type
.t
&& gnu_ext
)
4405 error("macro '%s' used with too few args",
4406 get_tok_str(s
->v
, 0));
4409 /* now subst each arg */
4410 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
4415 tok_str_free((int *)sa
->c
);
4421 sym_push2(nested_list
, s
->v
, 0, 0);
4422 macro_subst(tok_str
, nested_list
, mstr
, can_read_stream
);
4423 /* pop nested defined symbol */
4425 *nested_list
= sa1
->prev
;
4433 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4434 return the resulting string (which must be freed). */
4435 static inline int *macro_twosharps(const int *macro_str
)
4438 const int *ptr
, *saved_macro_ptr
;
4440 const char *p1
, *p2
;
4442 TokenString macro_str1
;
4445 /* we search the first '##' */
4446 for(ptr
= macro_str
;;) {
4447 TOK_GET(t
, ptr
, cval
);
4448 if (t
== TOK_TWOSHARPS
)
4450 /* nothing more to do if end of string */
4455 /* we saw '##', so we need more processing to handle it */
4457 tok_str_new(¯o_str1
);
4458 saved_macro_ptr
= macro_ptr
;
4459 /* XXX: get rid of the use of macro_ptr here */
4460 macro_ptr
= (int *)macro_str
;
4465 if (tok
== TOK_TWOSHARPS
)
4467 while (*macro_ptr
== TOK_TWOSHARPS
) {
4469 if (t
&& t
!= TOK_TWOSHARPS
) {
4470 TOK_GET(t
, macro_ptr
, cval
);
4471 /* We concatenate the two tokens if we have an
4472 identifier or a preprocessing number */
4474 p1
= get_tok_str(tok
, &tokc
);
4475 cstr_cat(&cstr
, p1
);
4476 p2
= get_tok_str(t
, &cval
);
4477 cstr_cat(&cstr
, p2
);
4478 cstr_ccat(&cstr
, '\0');
4480 if ((tok
>= TOK_IDENT
|| tok
== TOK_PPNUM
) &&
4481 (t
>= TOK_IDENT
|| t
== TOK_PPNUM
)) {
4482 if (tok
== TOK_PPNUM
) {
4483 /* if number, then create a number token */
4484 /* NOTE: no need to allocate because
4485 tok_str_add2() does it */
4486 cstr_reset(&tokcstr
);
4489 tokc
.cstr
= &tokcstr
;
4491 /* if identifier, we must do a test to
4492 validate we have a correct identifier */
4493 if (t
== TOK_PPNUM
) {
4503 if (!isnum(c
) && !isid(c
))
4507 ts
= tok_alloc(cstr
.data
, strlen(cstr
.data
));
4508 tok
= ts
->tok
; /* modify current token */
4511 const char *str
= cstr
.data
;
4512 const unsigned char *q
;
4514 /* we look for a valid token */
4515 /* XXX: do more extensive checks */
4516 if (!strcmp(str
, ">>=")) {
4518 } else if (!strcmp(str
, "<<=")) {
4520 } else if (strlen(str
) == 2) {
4521 /* search in two bytes table */
4526 if (q
[0] == str
[0] && q
[1] == str
[1])
4533 /* NOTE: because get_tok_str use a static buffer,
4536 p1
= get_tok_str(tok
, &tokc
);
4537 cstr_cat(&cstr
, p1
);
4538 cstr_ccat(&cstr
, '\0');
4539 p2
= get_tok_str(t
, &cval
);
4540 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr
.data
, p2
);
4541 /* cannot merge tokens: just add them separately */
4542 tok_str_add2(¯o_str1
, tok
, &tokc
);
4543 /* XXX: free associated memory ? */
4550 tok_str_add2(¯o_str1
, tok
, &tokc
);
4552 macro_ptr
= (int *)saved_macro_ptr
;
4554 tok_str_add(¯o_str1
, 0);
4555 return macro_str1
.str
;
4559 /* do macro substitution of macro_str and add result to
4560 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4561 inside to avoid recursing. */
4562 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
4563 const int *macro_str
, struct macro_level
** can_read_stream
)
4570 struct macro_level ml
;
4572 /* first scan for '##' operator handling */
4574 macro_str1
= macro_twosharps(ptr
);
4579 /* NOTE: ptr == NULL can only happen if tokens are read from
4580 file stream due to a macro function call */
4583 TOK_GET(t
, ptr
, cval
);
4588 /* if nested substitution, do nothing */
4589 if (sym_find2(*nested_list
, t
))
4592 if (can_read_stream
)
4593 ml
.prev
= *can_read_stream
, *can_read_stream
= &ml
;
4594 macro_ptr
= (int *)ptr
;
4596 ret
= macro_subst_tok(tok_str
, nested_list
, s
, can_read_stream
);
4597 ptr
= (int *)macro_ptr
;
4599 if (can_read_stream
&& *can_read_stream
== &ml
)
4600 *can_read_stream
= ml
.prev
;
4605 if (!check_space(t
, &spc
))
4606 tok_str_add2(tok_str
, t
, &cval
);
4610 tok_str_free(macro_str1
);
4613 /* return next token with macro substitution */
4614 static void next(void)
4616 Sym
*nested_list
, *s
;
4618 struct macro_level
*ml
;
4621 if (parse_flags
& PARSE_FLAG_SPACES
)
4626 /* if not reading from macro substituted string, then try
4627 to substitute macros */
4628 if (tok
>= TOK_IDENT
&&
4629 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
4630 s
= define_find(tok
);
4632 /* we have a macro: we try to substitute */
4636 if (macro_subst_tok(&str
, &nested_list
, s
, &ml
) == 0) {
4637 /* substitution done, NOTE: maybe empty */
4638 tok_str_add(&str
, 0);
4639 macro_ptr
= str
.str
;
4640 macro_ptr_allocated
= str
.str
;
4647 /* end of macro or end of unget buffer */
4648 if (unget_buffer_enabled
) {
4649 macro_ptr
= unget_saved_macro_ptr
;
4650 unget_buffer_enabled
= 0;
4652 /* end of macro string: free it */
4653 tok_str_free(macro_ptr_allocated
);
4660 /* convert preprocessor tokens into C tokens */
4661 if (tok
== TOK_PPNUM
&&
4662 (parse_flags
& PARSE_FLAG_TOK_NUM
)) {
4663 parse_number((char *)tokc
.cstr
->data
);
4667 /* push back current token and set current token to 'last_tok'. Only
4668 identifier case handled for labels. */
4669 static inline void unget_tok(int last_tok
)
4673 unget_saved_macro_ptr
= macro_ptr
;
4674 unget_buffer_enabled
= 1;
4675 q
= unget_saved_buffer
;
4678 n
= tok_ext_size(tok
) - 1;
4681 *q
= 0; /* end of token string */
4686 void swap(int *p
, int *q
)
4694 void vsetc(CType
*type
, int r
, CValue
*vc
)
4698 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4699 error("memory full");
4700 /* cannot let cpu flags if other instruction are generated. Also
4701 avoid leaving VT_JMP anywhere except on the top of the stack
4702 because it would complicate the code generator. */
4703 if (vtop
>= vstack
) {
4704 v
= vtop
->r
& VT_VALMASK
;
4705 if (v
== VT_CMP
|| (v
& ~1) == VT_JMP
)
4711 vtop
->r2
= VT_CONST
;
4715 /* push integer constant */
4720 vsetc(&int_type
, VT_CONST
, &cval
);
4723 /* push long long constant */
4724 void vpushll(long long v
)
4730 vsetc(&ctype
, VT_CONST
, &cval
);
4733 /* Return a static symbol pointing to a section */
4734 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
4735 unsigned long offset
, unsigned long size
)
4741 sym
= global_identifier_push(v
, type
->t
| VT_STATIC
, 0);
4742 sym
->type
.ref
= type
->ref
;
4743 sym
->r
= VT_CONST
| VT_SYM
;
4744 put_extern_sym(sym
, sec
, offset
, size
);
4748 /* push a reference to a section offset by adding a dummy symbol */
4749 static void vpush_ref(CType
*type
, Section
*sec
, unsigned long offset
, unsigned long size
)
4754 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4755 vtop
->sym
= get_sym_ref(type
, sec
, offset
, size
);
4758 /* define a new external reference to a symbol 'v' of type 'u' */
4759 static Sym
*external_global_sym(int v
, CType
*type
, int r
)
4765 /* push forward reference */
4766 s
= global_identifier_push(v
, type
->t
| VT_EXTERN
, 0);
4767 s
->type
.ref
= type
->ref
;
4768 s
->r
= r
| VT_CONST
| VT_SYM
;
4773 /* define a new external reference to a symbol 'v' of type 'u' */
4774 static Sym
*external_sym(int v
, CType
*type
, int r
)
4780 /* push forward reference */
4781 s
= sym_push(v
, type
, r
| VT_CONST
| VT_SYM
, 0);
4782 s
->type
.t
|= VT_EXTERN
;
4784 if (!is_compatible_types(&s
->type
, type
))
4785 error("incompatible types for redefinition of '%s'",
4786 get_tok_str(v
, NULL
));
4791 /* push a reference to global symbol v */
4792 static void vpush_global_sym(CType
*type
, int v
)
4797 sym
= external_global_sym(v
, type
, 0);
4799 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4803 void vset(CType
*type
, int r
, int v
)
4808 vsetc(type
, r
, &cval
);
4811 void vseti(int r
, int v
)
4827 void vpushv(SValue
*v
)
4829 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4830 error("memory full");
4840 /* save r to the memory stack, and mark it as being free */
4841 void save_reg(int r
)
4843 int l
, saved
, size
, align
;
4847 /* modify all stack values */
4850 for(p
=vstack
;p
<=vtop
;p
++) {
4851 if ((p
->r
& VT_VALMASK
) == r
||
4852 ((p
->type
.t
& VT_BTYPE
) == VT_LLONG
&& (p
->r2
& VT_VALMASK
) == r
)) {
4853 /* must save value on stack if not already done */
4855 /* NOTE: must reload 'r' because r might be equal to r2 */
4856 r
= p
->r
& VT_VALMASK
;
4857 /* store register in the stack */
4859 if ((p
->r
& VT_LVAL
) ||
4860 (!is_float(type
->t
) && (type
->t
& VT_BTYPE
) != VT_LLONG
))
4861 #ifdef TCC_TARGET_X86_64
4862 type
= &char_pointer_type
;
4866 size
= type_size(type
, &align
);
4867 loc
= (loc
- size
) & -align
;
4868 sv
.type
.t
= type
->t
;
4869 sv
.r
= VT_LOCAL
| VT_LVAL
;
4872 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
4873 /* x86 specific: need to pop fp register ST0 if saved */
4874 if (r
== TREG_ST0
) {
4875 o(0xd9dd); /* fstp %st(1) */
4878 #ifndef TCC_TARGET_X86_64
4879 /* special long long case */
4880 if ((type
->t
& VT_BTYPE
) == VT_LLONG
) {
4888 /* mark that stack entry as being saved on the stack */
4889 if (p
->r
& VT_LVAL
) {
4890 /* also clear the bounded flag because the
4891 relocation address of the function was stored in
4893 p
->r
= (p
->r
& ~(VT_VALMASK
| VT_BOUNDED
)) | VT_LLOCAL
;
4895 p
->r
= lvalue_type(p
->type
.t
) | VT_LOCAL
;
4903 /* find a register of class 'rc2' with at most one reference on stack.
4904 * If none, call get_reg(rc) */
4905 int get_reg_ex(int rc
, int rc2
)
4910 for(r
=0;r
<NB_REGS
;r
++) {
4911 if (reg_classes
[r
] & rc2
) {
4914 for(p
= vstack
; p
<= vtop
; p
++) {
4915 if ((p
->r
& VT_VALMASK
) == r
||
4916 (p
->r2
& VT_VALMASK
) == r
)
4926 /* find a free register of class 'rc'. If none, save one register */
4932 /* find a free register */
4933 for(r
=0;r
<NB_REGS
;r
++) {
4934 if (reg_classes
[r
] & rc
) {
4935 for(p
=vstack
;p
<=vtop
;p
++) {
4936 if ((p
->r
& VT_VALMASK
) == r
||
4937 (p
->r2
& VT_VALMASK
) == r
)
4945 /* no register left : free the first one on the stack (VERY
4946 IMPORTANT to start from the bottom to ensure that we don't
4947 spill registers used in gen_opi()) */
4948 for(p
=vstack
;p
<=vtop
;p
++) {
4949 r
= p
->r
& VT_VALMASK
;
4950 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
))
4952 /* also look at second register (if long long) */
4953 r
= p
->r2
& VT_VALMASK
;
4954 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
4960 /* Should never comes here */
4964 /* save registers up to (vtop - n) stack entry */
4965 void save_regs(int n
)
4970 for(p
= vstack
;p
<= p1
; p
++) {
4971 r
= p
->r
& VT_VALMASK
;
4978 /* move register 's' to 'r', and flush previous value of r to memory
4980 void move_reg(int r
, int s
)
4993 /* get address of vtop (vtop MUST BE an lvalue) */
4996 vtop
->r
&= ~VT_LVAL
;
4997 /* tricky: if saved lvalue, then we can go back to lvalue */
4998 if ((vtop
->r
& VT_VALMASK
) == VT_LLOCAL
)
4999 vtop
->r
= (vtop
->r
& ~(VT_VALMASK
| VT_LVAL_TYPE
)) | VT_LOCAL
| VT_LVAL
;
5002 #ifdef CONFIG_TCC_BCHECK
5003 /* generate lvalue bound code */
5009 vtop
->r
&= ~VT_MUSTBOUND
;
5010 /* if lvalue, then use checking code before dereferencing */
5011 if (vtop
->r
& VT_LVAL
) {
5012 /* if not VT_BOUNDED value, then make one */
5013 if (!(vtop
->r
& VT_BOUNDED
)) {
5014 lval_type
= vtop
->r
& (VT_LVAL_TYPE
| VT_LVAL
);
5015 /* must save type because we must set it to int to get pointer */
5017 vtop
->type
.t
= VT_INT
;
5020 gen_bounded_ptr_add();
5021 vtop
->r
|= lval_type
;
5024 /* then check for dereferencing */
5025 gen_bounded_ptr_deref();
5030 /* store vtop a register belonging to class 'rc'. lvalues are
5031 converted to values. Cannot be used if cannot be converted to
5032 register value (such as structures). */
5035 int r
, rc2
, bit_pos
, bit_size
, size
, align
, i
;
5037 /* NOTE: get_reg can modify vstack[] */
5038 if (vtop
->type
.t
& VT_BITFIELD
) {
5041 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
5042 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
5043 /* remove bit field info to avoid loops */
5044 vtop
->type
.t
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
5045 /* cast to int to propagate signedness in following ops */
5046 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
5051 if((vtop
->type
.t
& VT_UNSIGNED
) ||
5052 (vtop
->type
.t
& VT_BTYPE
) == VT_BOOL
)
5053 type
.t
|= VT_UNSIGNED
;
5055 /* generate shifts */
5056 vpushi(bits
- (bit_pos
+ bit_size
));
5058 vpushi(bits
- bit_size
);
5059 /* NOTE: transformed to SHR if unsigned */
5063 if (is_float(vtop
->type
.t
) &&
5064 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
5067 unsigned long offset
;
5068 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
5072 /* XXX: unify with initializers handling ? */
5073 /* CPUs usually cannot use float constants, so we store them
5074 generically in data segment */
5075 size
= type_size(&vtop
->type
, &align
);
5076 offset
= (data_section
->data_offset
+ align
- 1) & -align
;
5077 data_section
->data_offset
= offset
;
5078 /* XXX: not portable yet */
5079 #if defined(__i386__) || defined(__x86_64__)
5080 /* Zero pad x87 tenbyte long doubles */
5081 if (size
== LDOUBLE_SIZE
)
5082 vtop
->c
.tab
[2] &= 0xffff;
5084 ptr
= section_ptr_add(data_section
, size
);
5086 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
5090 ptr
[i
] = vtop
->c
.tab
[size
-1-i
];
5094 ptr
[i
] = vtop
->c
.tab
[i
];
5095 sym
= get_sym_ref(&vtop
->type
, data_section
, offset
, size
<< 2);
5096 vtop
->r
|= VT_LVAL
| VT_SYM
;
5100 #ifdef CONFIG_TCC_BCHECK
5101 if (vtop
->r
& VT_MUSTBOUND
)
5105 r
= vtop
->r
& VT_VALMASK
;
5109 /* need to reload if:
5111 - lvalue (need to dereference pointer)
5112 - already a register, but not in the right class */
5113 if (r
>= VT_CONST
||
5114 (vtop
->r
& VT_LVAL
) ||
5115 !(reg_classes
[r
] & rc
) ||
5116 ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
&&
5117 !(reg_classes
[vtop
->r2
] & rc2
))) {
5119 #ifndef TCC_TARGET_X86_64
5120 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
5122 unsigned long long ll
;
5123 /* two register type load : expand to two words
5125 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
5128 vtop
->c
.ui
= ll
; /* first word */
5130 vtop
->r
= r
; /* save register value */
5131 vpushi(ll
>> 32); /* second word */
5132 } else if (r
>= VT_CONST
|| /* XXX: test to VT_CONST incorrect ? */
5133 (vtop
->r
& VT_LVAL
)) {
5134 /* We do not want to modifier the long long
5135 pointer here, so the safest (and less
5136 efficient) is to save all the other registers
5137 in the stack. XXX: totally inefficient. */
5139 /* load from memory */
5142 vtop
[-1].r
= r
; /* save register value */
5143 /* increment pointer to get second word */
5144 vtop
->type
.t
= VT_INT
;
5150 /* move registers */
5153 vtop
[-1].r
= r
; /* save register value */
5154 vtop
->r
= vtop
[-1].r2
;
5156 /* allocate second register */
5160 /* write second register */
5164 if ((vtop
->r
& VT_LVAL
) && !is_float(vtop
->type
.t
)) {
5166 /* lvalue of scalar type : need to use lvalue type
5167 because of possible cast */
5170 /* compute memory access type */
5171 if (vtop
->r
& VT_LVAL_BYTE
)
5173 else if (vtop
->r
& VT_LVAL_SHORT
)
5175 if (vtop
->r
& VT_LVAL_UNSIGNED
)
5179 /* restore wanted type */
5182 /* one register type load */
5187 #ifdef TCC_TARGET_C67
5188 /* uses register pairs for doubles */
5189 if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
)
5196 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
5197 void gv2(int rc1
, int rc2
)
5201 /* generate more generic register first. But VT_JMP or VT_CMP
5202 values must be generated first in all cases to avoid possible
5204 v
= vtop
[0].r
& VT_VALMASK
;
5205 if (v
!= VT_CMP
&& (v
& ~1) != VT_JMP
&& rc1
<= rc2
) {
5210 /* test if reload is needed for first register */
5211 if ((vtop
[-1].r
& VT_VALMASK
) >= VT_CONST
) {
5221 /* test if reload is needed for first register */
5222 if ((vtop
[0].r
& VT_VALMASK
) >= VT_CONST
) {
5228 /* wrapper around RC_FRET to return a register by type */
5231 #ifdef TCC_TARGET_X86_64
5232 if (t
== VT_LDOUBLE
) {
5239 /* wrapper around REG_FRET to return a register by type */
5242 #ifdef TCC_TARGET_X86_64
5243 if (t
== VT_LDOUBLE
) {
5250 /* expand long long on stack in two int registers */
5255 u
= vtop
->type
.t
& VT_UNSIGNED
;
5258 vtop
[0].r
= vtop
[-1].r2
;
5259 vtop
[0].r2
= VT_CONST
;
5260 vtop
[-1].r2
= VT_CONST
;
5261 vtop
[0].type
.t
= VT_INT
| u
;
5262 vtop
[-1].type
.t
= VT_INT
| u
;
5265 #ifdef TCC_TARGET_ARM
5266 /* expand long long on stack */
5267 void lexpand_nr(void)
5271 u
= vtop
->type
.t
& VT_UNSIGNED
;
5273 vtop
->r2
= VT_CONST
;
5274 vtop
->type
.t
= VT_INT
| u
;
5275 v
=vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
);
5276 if (v
== VT_CONST
) {
5277 vtop
[-1].c
.ui
= vtop
->c
.ull
;
5278 vtop
->c
.ui
= vtop
->c
.ull
>> 32;
5280 } else if (v
== (VT_LVAL
|VT_CONST
) || v
== (VT_LVAL
|VT_LOCAL
)) {
5282 vtop
->r
= vtop
[-1].r
;
5283 } else if (v
> VT_CONST
) {
5287 vtop
->r
= vtop
[-1].r2
;
5288 vtop
[-1].r2
= VT_CONST
;
5289 vtop
[-1].type
.t
= VT_INT
| u
;
5293 /* build a long long from two ints */
5296 gv2(RC_INT
, RC_INT
);
5297 vtop
[-1].r2
= vtop
[0].r
;
5298 vtop
[-1].type
.t
= t
;
5302 /* rotate n first stack elements to the bottom
5303 I1 ... In -> I2 ... In I1 [top is right]
5311 for(i
=-n
+1;i
!=0;i
++)
5312 vtop
[i
] = vtop
[i
+1];
5316 /* rotate n first stack elements to the top
5317 I1 ... In -> In I1 ... I(n-1) [top is right]
5325 for(i
= 0;i
< n
- 1; i
++)
5326 vtop
[-i
] = vtop
[-i
- 1];
5330 #ifdef TCC_TARGET_ARM
5331 /* like vrott but in other direction
5332 In ... I1 -> I(n-1) ... I1 In [top is right]
5340 for(i
= n
- 1; i
> 0; i
--)
5341 vtop
[-i
] = vtop
[-i
+ 1];
5346 /* pop stack value */
5350 v
= vtop
->r
& VT_VALMASK
;
5351 #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
5352 /* for x86, we need to pop the FP stack */
5353 if (v
== TREG_ST0
&& !nocode_wanted
) {
5354 o(0xd9dd); /* fstp %st(1) */
5357 if (v
== VT_JMP
|| v
== VT_JMPI
) {
5358 /* need to put correct jump if && or || without test */
5364 /* convert stack entry to register and duplicate its value in another
5372 if ((t
& VT_BTYPE
) == VT_LLONG
) {
5379 /* stack: H L L1 H1 */
5387 /* duplicate value */
5392 #ifdef TCC_TARGET_X86_64
5393 if ((t
& VT_BTYPE
) == VT_LDOUBLE
) {
5403 load(r1
, &sv
); /* move r to r1 */
5405 /* duplicates value */
5410 #ifndef TCC_TARGET_X86_64
5411 /* generate CPU independent (unsigned) long long operations */
5412 void gen_opl(int op
)
5414 int t
, a
, b
, op1
, c
, i
;
5416 unsigned short reg_iret
= REG_IRET
;
5417 unsigned short reg_lret
= REG_LRET
;
5423 func
= TOK___divdi3
;
5426 func
= TOK___udivdi3
;
5429 func
= TOK___moddi3
;
5432 func
= TOK___umoddi3
;
5439 /* call generic long long function */
5440 vpush_global_sym(&func_old_type
, func
);
5445 vtop
->r2
= reg_lret
;
5458 /* stack: L1 H1 L2 H2 */
5463 vtop
[-2] = vtop
[-3];
5466 /* stack: H1 H2 L1 L2 */
5472 /* stack: H1 H2 L1 L2 ML MH */
5475 /* stack: ML MH H1 H2 L1 L2 */
5479 /* stack: ML MH H1 L2 H2 L1 */
5484 /* stack: ML MH M1 M2 */
5487 } else if (op
== '+' || op
== '-') {
5488 /* XXX: add non carry method too (for MIPS or alpha) */
5494 /* stack: H1 H2 (L1 op L2) */
5497 gen_op(op1
+ 1); /* TOK_xxxC2 */
5500 /* stack: H1 H2 (L1 op L2) */
5503 /* stack: (L1 op L2) H1 H2 */
5505 /* stack: (L1 op L2) (H1 op H2) */
5513 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
5514 t
= vtop
[-1].type
.t
;
5518 /* stack: L H shift */
5520 /* constant: simpler */
5521 /* NOTE: all comments are for SHL. the other cases are
5522 done by swaping words */
5533 if (op
!= TOK_SAR
) {
5566 /* XXX: should provide a faster fallback on x86 ? */
5569 func
= TOK___ashrdi3
;
5572 func
= TOK___lshrdi3
;
5575 func
= TOK___ashldi3
;
5581 /* compare operations */
5587 /* stack: L1 H1 L2 H2 */
5589 vtop
[-1] = vtop
[-2];
5591 /* stack: L1 L2 H1 H2 */
5594 /* when values are equal, we need to compare low words. since
5595 the jump is inverted, we invert the test too. */
5598 else if (op1
== TOK_GT
)
5600 else if (op1
== TOK_ULT
)
5602 else if (op1
== TOK_UGT
)
5607 if (op1
!= TOK_NE
) {
5611 /* generate non equal test */
5612 /* XXX: NOT PORTABLE yet */
5616 #if defined(TCC_TARGET_I386)
5617 b
= psym(0x850f, 0);
5618 #elif defined(TCC_TARGET_ARM)
5620 o(0x1A000000 | encbranch(ind
, 0, 1));
5621 #elif defined(TCC_TARGET_C67)
5622 error("not implemented");
5624 #error not supported
5628 /* compare low. Always unsigned */
5632 else if (op1
== TOK_LE
)
5634 else if (op1
== TOK_GT
)
5636 else if (op1
== TOK_GE
)
5647 /* handle integer constant optimizations and various machine
5649 void gen_opic(int op
)
5651 int c1
, c2
, t1
, t2
, n
;
5654 typedef unsigned long long U
;
5658 t1
= v1
->type
.t
& VT_BTYPE
;
5659 t2
= v2
->type
.t
& VT_BTYPE
;
5663 else if (v1
->type
.t
& VT_UNSIGNED
)
5670 else if (v2
->type
.t
& VT_UNSIGNED
)
5675 /* currently, we cannot do computations with forward symbols */
5676 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5677 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5680 case '+': l1
+= l2
; break;
5681 case '-': l1
-= l2
; break;
5682 case '&': l1
&= l2
; break;
5683 case '^': l1
^= l2
; break;
5684 case '|': l1
|= l2
; break;
5685 case '*': l1
*= l2
; break;
5692 /* if division by zero, generate explicit division */
5695 error("division by zero in constant");
5699 default: l1
/= l2
; break;
5700 case '%': l1
%= l2
; break;
5701 case TOK_UDIV
: l1
= (U
)l1
/ l2
; break;
5702 case TOK_UMOD
: l1
= (U
)l1
% l2
; break;
5705 case TOK_SHL
: l1
<<= l2
; break;
5706 case TOK_SHR
: l1
= (U
)l1
>> l2
; break;
5707 case TOK_SAR
: l1
>>= l2
; break;
5709 case TOK_ULT
: l1
= (U
)l1
< (U
)l2
; break;
5710 case TOK_UGE
: l1
= (U
)l1
>= (U
)l2
; break;
5711 case TOK_EQ
: l1
= l1
== l2
; break;
5712 case TOK_NE
: l1
= l1
!= l2
; break;
5713 case TOK_ULE
: l1
= (U
)l1
<= (U
)l2
; break;
5714 case TOK_UGT
: l1
= (U
)l1
> (U
)l2
; break;
5715 case TOK_LT
: l1
= l1
< l2
; break;
5716 case TOK_GE
: l1
= l1
>= l2
; break;
5717 case TOK_LE
: l1
= l1
<= l2
; break;
5718 case TOK_GT
: l1
= l1
> l2
; break;
5720 case TOK_LAND
: l1
= l1
&& l2
; break;
5721 case TOK_LOR
: l1
= l1
|| l2
; break;
5728 /* if commutative ops, put c2 as constant */
5729 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
5730 op
== '|' || op
== '*')) {
5732 c2
= c1
; //c = c1, c1 = c2, c2 = c;
5733 l2
= l1
; //l = l1, l1 = l2, l2 = l;
5735 /* Filter out NOP operations like x*1, x-0, x&-1... */
5736 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
5739 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
5740 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
5746 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
5747 /* try to use shifts instead of muls or divs */
5748 if (l2
> 0 && (l2
& (l2
- 1)) == 0) {
5757 else if (op
== TOK_PDIV
)
5763 } else if (c2
&& (op
== '+' || op
== '-') &&
5764 ((vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) ==
5765 (VT_CONST
| VT_SYM
) ||
5766 (vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
)) == VT_LOCAL
)) {
5767 /* symbol + constant case */
5774 if (!nocode_wanted
) {
5775 /* call low level op generator */
5776 if (t1
== VT_LLONG
|| t2
== VT_LLONG
)
5787 /* generate a floating point operation with constant propagation */
5788 void gen_opif(int op
)
5796 /* currently, we cannot do computations with forward symbols */
5797 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5798 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5800 if (v1
->type
.t
== VT_FLOAT
) {
5803 } else if (v1
->type
.t
== VT_DOUBLE
) {
5811 /* NOTE: we only do constant propagation if finite number (not
5812 NaN or infinity) (ANSI spec) */
5813 if (!ieee_finite(f1
) || !ieee_finite(f2
))
5817 case '+': f1
+= f2
; break;
5818 case '-': f1
-= f2
; break;
5819 case '*': f1
*= f2
; break;
5823 error("division by zero in constant");
5828 /* XXX: also handles tests ? */
5832 /* XXX: overflow test ? */
5833 if (v1
->type
.t
== VT_FLOAT
) {
5835 } else if (v1
->type
.t
== VT_DOUBLE
) {
5843 if (!nocode_wanted
) {
5851 static int pointed_size(CType
*type
)
5854 return type_size(pointed_type(type
), &align
);
5857 static inline int is_null_pointer(SValue
*p
)
5859 if ((p
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
5861 return ((p
->type
.t
& VT_BTYPE
) == VT_INT
&& p
->c
.i
== 0) ||
5862 ((p
->type
.t
& VT_BTYPE
) == VT_LLONG
&& p
->c
.ll
== 0);
5865 static inline int is_integer_btype(int bt
)
5867 return (bt
== VT_BYTE
|| bt
== VT_SHORT
||
5868 bt
== VT_INT
|| bt
== VT_LLONG
);
5871 /* check types for comparison or substraction of pointers */
5872 static void check_comparison_pointer_types(SValue
*p1
, SValue
*p2
, int op
)
5874 CType
*type1
, *type2
, tmp_type1
, tmp_type2
;
5877 /* null pointers are accepted for all comparisons as gcc */
5878 if (is_null_pointer(p1
) || is_null_pointer(p2
))
5882 bt1
= type1
->t
& VT_BTYPE
;
5883 bt2
= type2
->t
& VT_BTYPE
;
5884 /* accept comparison between pointer and integer with a warning */
5885 if ((is_integer_btype(bt1
) || is_integer_btype(bt2
)) && op
!= '-') {
5886 if (op
!= TOK_LOR
&& op
!= TOK_LAND
)
5887 warning("comparison between pointer and integer");
5891 /* both must be pointers or implicit function pointers */
5892 if (bt1
== VT_PTR
) {
5893 type1
= pointed_type(type1
);
5894 } else if (bt1
!= VT_FUNC
)
5895 goto invalid_operands
;
5897 if (bt2
== VT_PTR
) {
5898 type2
= pointed_type(type2
);
5899 } else if (bt2
!= VT_FUNC
) {
5901 error("invalid operands to binary %s", get_tok_str(op
, NULL
));
5903 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
5904 (type2
->t
& VT_BTYPE
) == VT_VOID
)
5908 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5909 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5910 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
5911 /* gcc-like error if '-' is used */
5913 goto invalid_operands
;
5915 warning("comparison of distinct pointer types lacks a cast");
5919 /* generic gen_op: handles types problems */
5922 int u
, t1
, t2
, bt1
, bt2
, t
;
5925 t1
= vtop
[-1].type
.t
;
5926 t2
= vtop
[0].type
.t
;
5927 bt1
= t1
& VT_BTYPE
;
5928 bt2
= t2
& VT_BTYPE
;
5930 if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
5931 /* at least one operand is a pointer */
5932 /* relationnal op: must be both pointers */
5933 if (op
>= TOK_ULT
&& op
<= TOK_LOR
) {
5934 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5935 /* pointers are handled are unsigned */
5936 #ifdef TCC_TARGET_X86_64
5937 t
= VT_LLONG
| VT_UNSIGNED
;
5939 t
= VT_INT
| VT_UNSIGNED
;
5943 /* if both pointers, then it must be the '-' op */
5944 if (bt1
== VT_PTR
&& bt2
== VT_PTR
) {
5946 error("cannot use pointers here");
5947 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5948 /* XXX: check that types are compatible */
5949 u
= pointed_size(&vtop
[-1].type
);
5951 /* set to integer type */
5952 #ifdef TCC_TARGET_X86_64
5953 vtop
->type
.t
= VT_LLONG
;
5955 vtop
->type
.t
= VT_INT
;
5960 /* exactly one pointer : must be '+' or '-'. */
5961 if (op
!= '-' && op
!= '+')
5962 error("cannot use pointers here");
5963 /* Put pointer as first operand */
5964 if (bt2
== VT_PTR
) {
5968 type1
= vtop
[-1].type
;
5969 #ifdef TCC_TARGET_X86_64
5970 vpushll(pointed_size(&vtop
[-1].type
));
5972 /* XXX: cast to int ? (long long case) */
5973 vpushi(pointed_size(&vtop
[-1].type
));
5976 #ifdef CONFIG_TCC_BCHECK
5977 /* if evaluating constant expression, no code should be
5978 generated, so no bound check */
5979 if (do_bounds_check
&& !const_wanted
) {
5980 /* if bounded pointers, we generate a special code to
5987 gen_bounded_ptr_add();
5993 /* put again type if gen_opic() swaped operands */
5996 } else if (is_float(bt1
) || is_float(bt2
)) {
5997 /* compute bigger type and do implicit casts */
5998 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
6000 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
6005 /* floats can only be used for a few operations */
6006 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
6007 (op
< TOK_ULT
|| op
> TOK_GT
))
6008 error("invalid operands for binary operation");
6010 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
6011 /* cast to biggest op */
6013 /* convert to unsigned if it does not fit in a long long */
6014 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
6015 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
6019 /* integer operations */
6021 /* convert to unsigned if it does not fit in an integer */
6022 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
6023 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
6026 /* XXX: currently, some unsigned operations are explicit, so
6027 we modify them here */
6028 if (t
& VT_UNSIGNED
) {
6035 else if (op
== TOK_LT
)
6037 else if (op
== TOK_GT
)
6039 else if (op
== TOK_LE
)
6041 else if (op
== TOK_GE
)
6048 /* special case for shifts and long long: we keep the shift as
6050 if (op
== TOK_SHR
|| op
== TOK_SAR
|| op
== TOK_SHL
)
6057 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
6058 /* relationnal op: the result is an int */
6059 vtop
->type
.t
= VT_INT
;
6066 #ifndef TCC_TARGET_ARM
6067 /* generic itof for unsigned long long case */
6068 void gen_cvt_itof1(int t
)
6070 if ((vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
)) ==
6071 (VT_LLONG
| VT_UNSIGNED
)) {
6074 vpush_global_sym(&func_old_type
, TOK___floatundisf
);
6075 #if LDOUBLE_SIZE != 8
6076 else if (t
== VT_LDOUBLE
)
6077 vpush_global_sym(&func_old_type
, TOK___floatundixf
);
6080 vpush_global_sym(&func_old_type
, TOK___floatundidf
);
6084 vtop
->r
= reg_fret(t
);
6091 /* generic ftoi for unsigned long long case */
6092 void gen_cvt_ftoi1(int t
)
6096 if (t
== (VT_LLONG
| VT_UNSIGNED
)) {
6097 /* not handled natively */
6098 st
= vtop
->type
.t
& VT_BTYPE
;
6100 vpush_global_sym(&func_old_type
, TOK___fixunssfdi
);
6101 #if LDOUBLE_SIZE != 8
6102 else if (st
== VT_LDOUBLE
)
6103 vpush_global_sym(&func_old_type
, TOK___fixunsxfdi
);
6106 vpush_global_sym(&func_old_type
, TOK___fixunsdfdi
);
6111 vtop
->r2
= REG_LRET
;
6117 /* force char or short cast */
6118 void force_charshort_cast(int t
)
6122 /* XXX: add optimization if lvalue : just change type and offset */
6127 if (t
& VT_UNSIGNED
) {
6128 vpushi((1 << bits
) - 1);
6134 /* result must be signed or the SAR is converted to an SHL
6135 This was not the case when "t" was a signed short
6136 and the last value on the stack was an unsigned int */
6137 vtop
->type
.t
&= ~VT_UNSIGNED
;
6143 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
6144 static void gen_cast(CType
*type
)
6146 int sbt
, dbt
, sf
, df
, c
, p
;
6148 /* special delayed cast for char/short */
6149 /* XXX: in some cases (multiple cascaded casts), it may still
6151 if (vtop
->r
& VT_MUSTCAST
) {
6152 vtop
->r
&= ~VT_MUSTCAST
;
6153 force_charshort_cast(vtop
->type
.t
);
6156 /* bitfields first get cast to ints */
6157 if (vtop
->type
.t
& VT_BITFIELD
) {
6161 dbt
= type
->t
& (VT_BTYPE
| VT_UNSIGNED
);
6162 sbt
= vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
);
6167 c
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
6168 p
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == (VT_CONST
| VT_SYM
);
6170 /* constant case: we can do it now */
6171 /* XXX: in ISOC, cannot do it if error in convert */
6172 if (sbt
== VT_FLOAT
)
6173 vtop
->c
.ld
= vtop
->c
.f
;
6174 else if (sbt
== VT_DOUBLE
)
6175 vtop
->c
.ld
= vtop
->c
.d
;
6178 if ((sbt
& VT_BTYPE
) == VT_LLONG
) {
6179 if (sbt
& VT_UNSIGNED
)
6180 vtop
->c
.ld
= vtop
->c
.ull
;
6182 vtop
->c
.ld
= vtop
->c
.ll
;
6184 if (sbt
& VT_UNSIGNED
)
6185 vtop
->c
.ld
= vtop
->c
.ui
;
6187 vtop
->c
.ld
= vtop
->c
.i
;
6190 if (dbt
== VT_FLOAT
)
6191 vtop
->c
.f
= (float)vtop
->c
.ld
;
6192 else if (dbt
== VT_DOUBLE
)
6193 vtop
->c
.d
= (double)vtop
->c
.ld
;
6194 } else if (sf
&& dbt
== (VT_LLONG
|VT_UNSIGNED
)) {
6195 vtop
->c
.ull
= (unsigned long long)vtop
->c
.ld
;
6196 } else if (sf
&& dbt
== VT_BOOL
) {
6197 vtop
->c
.i
= (vtop
->c
.ld
!= 0);
6200 vtop
->c
.ll
= (long long)vtop
->c
.ld
;
6201 else if (sbt
== (VT_LLONG
|VT_UNSIGNED
))
6202 vtop
->c
.ll
= vtop
->c
.ull
;
6203 else if (sbt
& VT_UNSIGNED
)
6204 vtop
->c
.ll
= vtop
->c
.ui
;
6205 else if (sbt
!= VT_LLONG
)
6206 vtop
->c
.ll
= vtop
->c
.i
;
6208 if (dbt
== (VT_LLONG
|VT_UNSIGNED
))
6209 vtop
->c
.ull
= vtop
->c
.ll
;
6210 else if (dbt
== VT_BOOL
)
6211 vtop
->c
.i
= (vtop
->c
.ll
!= 0);
6212 else if (dbt
!= VT_LLONG
) {
6214 if ((dbt
& VT_BTYPE
) == VT_BYTE
)
6216 else if ((dbt
& VT_BTYPE
) == VT_SHORT
)
6219 if(dbt
& VT_UNSIGNED
)
6220 vtop
->c
.ui
= ((unsigned int)vtop
->c
.ll
<< s
) >> s
;
6222 vtop
->c
.i
= ((int)vtop
->c
.ll
<< s
) >> s
;
6225 } else if (p
&& dbt
== VT_BOOL
) {
6228 } else if (!nocode_wanted
) {
6229 /* non constant case: generate code */
6231 /* convert from fp to fp */
6234 /* convert int to fp */
6237 /* convert fp to int */
6238 if (dbt
== VT_BOOL
) {
6242 /* we handle char/short/etc... with generic code */
6243 if (dbt
!= (VT_INT
| VT_UNSIGNED
) &&
6244 dbt
!= (VT_LLONG
| VT_UNSIGNED
) &&
6248 if (dbt
== VT_INT
&& (type
->t
& (VT_BTYPE
| VT_UNSIGNED
)) != dbt
) {
6249 /* additional cast for char/short... */
6254 #ifndef TCC_TARGET_X86_64
6255 } else if ((dbt
& VT_BTYPE
) == VT_LLONG
) {
6256 if ((sbt
& VT_BTYPE
) != VT_LLONG
) {
6257 /* scalar to long long */
6258 /* machine independent conversion */
6260 /* generate high word */
6261 if (sbt
== (VT_INT
| VT_UNSIGNED
)) {
6265 if (sbt
== VT_PTR
) {
6266 /* cast from pointer to int before we apply
6267 shift operation, which pointers don't support*/
6268 gen_cast(&int_type
);
6274 /* patch second register */
6275 vtop
[-1].r2
= vtop
->r
;
6279 } else if ((dbt
& VT_BTYPE
) == VT_LLONG
||
6280 (dbt
& VT_BTYPE
) == VT_PTR
) {
6281 /* XXX: not sure if this is perfect... need more tests */
6282 if ((sbt
& VT_BTYPE
) != VT_LLONG
) {
6284 if (sbt
!= (VT_INT
| VT_UNSIGNED
) &&
6285 sbt
!= VT_PTR
&& sbt
!= VT_FUNC
) {
6286 /* x86_64 specific: movslq */
6288 o(0xc0 + (REG_VALUE(r
) << 3) + REG_VALUE(r
));
6292 } else if (dbt
== VT_BOOL
) {
6293 /* scalar to bool */
6296 } else if ((dbt
& VT_BTYPE
) == VT_BYTE
||
6297 (dbt
& VT_BTYPE
) == VT_SHORT
) {
6298 if (sbt
== VT_PTR
) {
6299 vtop
->type
.t
= VT_INT
;
6300 warning("nonportable conversion from pointer to char/short");
6302 force_charshort_cast(dbt
);
6303 } else if ((dbt
& VT_BTYPE
) == VT_INT
) {
6305 if (sbt
== VT_LLONG
) {
6306 /* from long long: just take low order word */
6310 /* if lvalue and single word type, nothing to do because
6311 the lvalue already contains the real type size (see
6312 VT_LVAL_xxx constants) */
6315 } else if ((dbt
& VT_BTYPE
) == VT_PTR
&& !(vtop
->r
& VT_LVAL
)) {
6316 /* if we are casting between pointer types,
6317 we must update the VT_LVAL_xxx size */
6318 vtop
->r
= (vtop
->r
& ~VT_LVAL_TYPE
)
6319 | (lvalue_type(type
->ref
->type
.t
) & VT_LVAL_TYPE
);
6324 /* return type size. Put alignment at 'a' */
6325 static int type_size(CType
*type
, int *a
)
6330 bt
= type
->t
& VT_BTYPE
;
6331 if (bt
== VT_STRUCT
) {
6336 } else if (bt
== VT_PTR
) {
6337 if (type
->t
& VT_ARRAY
) {
6341 ts
= type_size(&s
->type
, a
);
6343 if (ts
< 0 && s
->c
< 0)
6351 } else if (bt
== VT_LDOUBLE
) {
6353 return LDOUBLE_SIZE
;
6354 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
6355 #ifdef TCC_TARGET_I386
6356 #ifdef TCC_TARGET_PE
6361 #elif defined(TCC_TARGET_ARM)
6371 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
6374 } else if (bt
== VT_SHORT
) {
6378 /* char, void, function, _Bool */
6384 /* return the pointed type of t */
6385 static inline CType
*pointed_type(CType
*type
)
6387 return &type
->ref
->type
;
6390 /* modify type so that its it is a pointer to type. */
6391 static void mk_pointer(CType
*type
)
6394 s
= sym_push(SYM_FIELD
, type
, 0, -1);
6395 type
->t
= VT_PTR
| (type
->t
& ~VT_TYPE
);
6399 /* compare function types. OLD functions match any new functions */
6400 static int is_compatible_func(CType
*type1
, CType
*type2
)
6406 if (!is_compatible_types(&s1
->type
, &s2
->type
))
6408 /* check func_call */
6409 if (FUNC_CALL(s1
->r
) != FUNC_CALL(s2
->r
))
6411 /* XXX: not complete */
6412 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
6416 while (s1
!= NULL
) {
6419 if (!is_compatible_parameter_types(&s1
->type
, &s2
->type
))
6429 /* return true if type1 and type2 are the same. If unqualified is
6430 true, qualifiers on the types are ignored.
6432 - enums are not checked as gcc __builtin_types_compatible_p ()
6434 static int compare_types(CType
*type1
, CType
*type2
, int unqualified
)
6438 t1
= type1
->t
& VT_TYPE
;
6439 t2
= type2
->t
& VT_TYPE
;
6441 /* strip qualifiers before comparing */
6442 t1
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6443 t2
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6445 /* XXX: bitfields ? */
6448 /* test more complicated cases */
6449 bt1
= t1
& VT_BTYPE
;
6450 if (bt1
== VT_PTR
) {
6451 type1
= pointed_type(type1
);
6452 type2
= pointed_type(type2
);
6453 return is_compatible_types(type1
, type2
);
6454 } else if (bt1
== VT_STRUCT
) {
6455 return (type1
->ref
== type2
->ref
);
6456 } else if (bt1
== VT_FUNC
) {
6457 return is_compatible_func(type1
, type2
);
6463 /* return true if type1 and type2 are exactly the same (including
6466 static int is_compatible_types(CType
*type1
, CType
*type2
)
6468 return compare_types(type1
,type2
,0);
6471 /* return true if type1 and type2 are the same (ignoring qualifiers).
6473 static int is_compatible_parameter_types(CType
*type1
, CType
*type2
)
6475 return compare_types(type1
,type2
,1);
6478 /* print a type. If 'varstr' is not NULL, then the variable is also
6479 printed in the type */
6481 /* XXX: add array and function pointers */
6482 void type_to_str(char *buf
, int buf_size
,
6483 CType
*type
, const char *varstr
)
6490 t
= type
->t
& VT_TYPE
;
6493 if (t
& VT_CONSTANT
)
6494 pstrcat(buf
, buf_size
, "const ");
6495 if (t
& VT_VOLATILE
)
6496 pstrcat(buf
, buf_size
, "volatile ");
6497 if (t
& VT_UNSIGNED
)
6498 pstrcat(buf
, buf_size
, "unsigned ");
6528 tstr
= "long double";
6530 pstrcat(buf
, buf_size
, tstr
);
6534 if (bt
== VT_STRUCT
)
6538 pstrcat(buf
, buf_size
, tstr
);
6539 v
= type
->ref
->v
& ~SYM_STRUCT
;
6540 if (v
>= SYM_FIRST_ANOM
)
6541 pstrcat(buf
, buf_size
, "<anonymous>");
6543 pstrcat(buf
, buf_size
, get_tok_str(v
, NULL
));
6547 type_to_str(buf
, buf_size
, &s
->type
, varstr
);
6548 pstrcat(buf
, buf_size
, "(");
6550 while (sa
!= NULL
) {
6551 type_to_str(buf1
, sizeof(buf1
), &sa
->type
, NULL
);
6552 pstrcat(buf
, buf_size
, buf1
);
6555 pstrcat(buf
, buf_size
, ", ");
6557 pstrcat(buf
, buf_size
, ")");
6561 pstrcpy(buf1
, sizeof(buf1
), "*");
6563 pstrcat(buf1
, sizeof(buf1
), varstr
);
6564 type_to_str(buf
, buf_size
, &s
->type
, buf1
);
6568 pstrcat(buf
, buf_size
, " ");
6569 pstrcat(buf
, buf_size
, varstr
);
6574 /* verify type compatibility to store vtop in 'dt' type, and generate
6576 static void gen_assign_cast(CType
*dt
)
6578 CType
*st
, *type1
, *type2
, tmp_type1
, tmp_type2
;
6579 char buf1
[256], buf2
[256];
6582 st
= &vtop
->type
; /* source type */
6583 dbt
= dt
->t
& VT_BTYPE
;
6584 sbt
= st
->t
& VT_BTYPE
;
6585 if (dt
->t
& VT_CONSTANT
)
6586 warning("assignment of read-only location");
6589 /* special cases for pointers */
6590 /* '0' can also be a pointer */
6591 if (is_null_pointer(vtop
))
6593 /* accept implicit pointer to integer cast with warning */
6594 if (is_integer_btype(sbt
)) {
6595 warning("assignment makes pointer from integer without a cast");
6598 type1
= pointed_type(dt
);
6599 /* a function is implicitely a function pointer */
6600 if (sbt
== VT_FUNC
) {
6601 if ((type1
->t
& VT_BTYPE
) != VT_VOID
&&
6602 !is_compatible_types(pointed_type(dt
), st
))
6609 type2
= pointed_type(st
);
6610 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
6611 (type2
->t
& VT_BTYPE
) == VT_VOID
) {
6612 /* void * can match anything */
6614 /* exact type match, except for unsigned */
6617 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6618 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6619 if (!is_compatible_types(&tmp_type1
, &tmp_type2
))
6620 warning("assignment from incompatible pointer type");
6622 /* check const and volatile */
6623 if ((!(type1
->t
& VT_CONSTANT
) && (type2
->t
& VT_CONSTANT
)) ||
6624 (!(type1
->t
& VT_VOLATILE
) && (type2
->t
& VT_VOLATILE
)))
6625 warning("assignment discards qualifiers from pointer target type");
6631 if (sbt
== VT_PTR
|| sbt
== VT_FUNC
) {
6632 warning("assignment makes integer from pointer without a cast");
6634 /* XXX: more tests */
6639 tmp_type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6640 tmp_type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6641 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
6643 type_to_str(buf1
, sizeof(buf1
), st
, NULL
);
6644 type_to_str(buf2
, sizeof(buf2
), dt
, NULL
);
6645 error("cannot cast '%s' to '%s'", buf1
, buf2
);
6653 /* store vtop in lvalue pushed on stack */
6656 int sbt
, dbt
, ft
, r
, t
, size
, align
, bit_size
, bit_pos
, rc
, delayed_cast
;
6658 ft
= vtop
[-1].type
.t
;
6659 sbt
= vtop
->type
.t
& VT_BTYPE
;
6660 dbt
= ft
& VT_BTYPE
;
6661 if (((sbt
== VT_INT
|| sbt
== VT_SHORT
) && dbt
== VT_BYTE
) ||
6662 (sbt
== VT_INT
&& dbt
== VT_SHORT
)) {
6663 /* optimize char/short casts */
6664 delayed_cast
= VT_MUSTCAST
;
6665 vtop
->type
.t
= ft
& (VT_TYPE
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
)));
6666 /* XXX: factorize */
6667 if (ft
& VT_CONSTANT
)
6668 warning("assignment of read-only location");
6671 if (!(ft
& VT_BITFIELD
))
6672 gen_assign_cast(&vtop
[-1].type
);
6675 if (sbt
== VT_STRUCT
) {
6676 /* if structure, only generate pointer */
6677 /* structure assignment : generate memcpy */
6678 /* XXX: optimize if small size */
6679 if (!nocode_wanted
) {
6680 size
= type_size(&vtop
->type
, &align
);
6684 vpush_global_sym(&func_old_type
, TOK_memcpy8
);
6685 else if(!(align
& 3))
6686 vpush_global_sym(&func_old_type
, TOK_memcpy4
);
6689 vpush_global_sym(&func_old_type
, TOK_memcpy
);
6693 vtop
->type
.t
= VT_PTR
;
6697 vtop
->type
.t
= VT_PTR
;
6709 /* leave source on stack */
6710 } else if (ft
& VT_BITFIELD
) {
6711 /* bitfield store handling */
6712 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
6713 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
6714 /* remove bit field info to avoid loops */
6715 vtop
[-1].type
.t
= ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
6717 /* duplicate source into other register */
6722 if((ft
& VT_BTYPE
) == VT_BOOL
) {
6723 gen_cast(&vtop
[-1].type
);
6724 vtop
[-1].type
.t
= (vtop
[-1].type
.t
& ~VT_BTYPE
) | (VT_BYTE
| VT_UNSIGNED
);
6727 /* duplicate destination */
6729 vtop
[-1] = vtop
[-2];
6731 /* mask and shift source */
6732 if((ft
& VT_BTYPE
) != VT_BOOL
) {
6733 if((ft
& VT_BTYPE
) == VT_LLONG
) {
6734 vpushll((1ULL << bit_size
) - 1ULL);
6736 vpushi((1 << bit_size
) - 1);
6742 /* load destination, mask and or with source */
6744 if((ft
& VT_BTYPE
) == VT_LLONG
) {
6745 vpushll(~(((1ULL << bit_size
) - 1ULL) << bit_pos
));
6747 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
6754 /* pop off shifted source from "duplicate source..." above */
6758 #ifdef CONFIG_TCC_BCHECK
6759 /* bound check case */
6760 if (vtop
[-1].r
& VT_MUSTBOUND
) {
6766 if (!nocode_wanted
) {
6770 #ifdef TCC_TARGET_X86_64
6771 if ((ft
& VT_BTYPE
) == VT_LDOUBLE
) {
6776 r
= gv(rc
); /* generate value */
6777 /* if lvalue was saved on stack, must read it */
6778 if ((vtop
[-1].r
& VT_VALMASK
) == VT_LLOCAL
) {
6780 t
= get_reg(RC_INT
);
6781 #ifdef TCC_TARGET_X86_64
6786 sv
.r
= VT_LOCAL
| VT_LVAL
;
6787 sv
.c
.ul
= vtop
[-1].c
.ul
;
6789 vtop
[-1].r
= t
| VT_LVAL
;
6792 #ifndef TCC_TARGET_X86_64
6793 /* two word case handling : store second register at word + 4 */
6794 if ((ft
& VT_BTYPE
) == VT_LLONG
) {
6796 /* convert to int to increment easily */
6797 vtop
->type
.t
= VT_INT
;
6803 /* XXX: it works because r2 is spilled last ! */
6804 store(vtop
->r2
, vtop
- 1);
6809 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
6810 vtop
->r
|= delayed_cast
;
6814 /* post defines POST/PRE add. c is the token ++ or -- */
6815 void inc(int post
, int c
)
6818 vdup(); /* save lvalue */
6820 gv_dup(); /* duplicate value */
6825 vpushi(c
- TOK_MID
);
6827 vstore(); /* store value */
6829 vpop(); /* if post op, return saved value */
6832 /* Parse GNUC __attribute__ extension. Currently, the following
6833 extensions are recognized:
6834 - aligned(n) : set data/function alignment.
6835 - packed : force data alignment to 1
6836 - section(x) : generate data/code in this section.
6837 - unused : currently ignored, but may be used someday.
6838 - regparm(n) : pass function parameters in registers (i386 only)
6840 static void parse_attribute(AttributeDef
*ad
)
6844 while (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
) {
6848 while (tok
!= ')') {
6849 if (tok
< TOK_IDENT
)
6850 expect("attribute name");
6858 expect("section name");
6859 ad
->section
= find_section(tcc_state
, (char *)tokc
.cstr
->data
);
6868 if (n
<= 0 || (n
& (n
- 1)) != 0)
6869 error("alignment must be a positive power of two");
6882 /* currently, no need to handle it because tcc does not
6883 track unused objects */
6887 /* currently, no need to handle it because tcc does not
6888 track unused objects */
6893 FUNC_CALL(ad
->func_attr
) = FUNC_CDECL
;
6898 FUNC_CALL(ad
->func_attr
) = FUNC_STDCALL
;
6900 #ifdef TCC_TARGET_I386
6910 FUNC_CALL(ad
->func_attr
) = FUNC_FASTCALL1
+ n
- 1;
6916 FUNC_CALL(ad
->func_attr
) = FUNC_FASTCALLW
;
6920 FUNC_EXPORT(ad
->func_attr
) = 1;
6923 if (tcc_state
->warn_unsupported
)
6924 warning("'%s' attribute ignored", get_tok_str(t
, NULL
));
6925 /* skip parameters */
6927 int parenthesis
= 0;
6931 else if (tok
== ')')
6934 } while (parenthesis
&& tok
!= -1);
6947 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6948 static void struct_decl(CType
*type
, int u
)
6950 int a
, v
, size
, align
, maxalign
, c
, offset
;
6951 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
, prevbt
;
6952 Sym
*s
, *ss
, *ass
, **ps
;
6956 a
= tok
; /* save decl type */
6961 /* struct already defined ? return it */
6963 expect("struct/union/enum name");
6967 error("invalid type");
6974 /* we put an undefined size for struct/union */
6975 s
= sym_push(v
| SYM_STRUCT
, &type1
, 0, -1);
6976 s
->r
= 0; /* default alignment is zero as gcc */
6977 /* put struct/union/enum name in type */
6985 error("struct/union/enum already defined");
6986 /* cannot be empty */
6988 /* non empty enums are not allowed */
6989 if (a
== TOK_ENUM
) {
6993 expect("identifier");
6999 /* enum symbols have static storage */
7000 ss
= sym_push(v
, &int_type
, VT_CONST
, c
);
7001 ss
->type
.t
|= VT_STATIC
;
7006 /* NOTE: we accept a trailing comma */
7017 while (tok
!= '}') {
7018 parse_btype(&btype
, &ad
);
7024 type_decl(&type1
, &ad
, &v
, TYPE_DIRECT
| TYPE_ABSTRACT
);
7025 if (v
== 0 && (type1
.t
& VT_BTYPE
) != VT_STRUCT
)
7026 expect("identifier");
7027 if ((type1
.t
& VT_BTYPE
) == VT_FUNC
||
7028 (type1
.t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
| VT_INLINE
)))
7029 error("invalid type for '%s'",
7030 get_tok_str(v
, NULL
));
7034 bit_size
= expr_const();
7035 /* XXX: handle v = 0 case for messages */
7037 error("negative width in bit-field '%s'",
7038 get_tok_str(v
, NULL
));
7039 if (v
&& bit_size
== 0)
7040 error("zero width for bit-field '%s'",
7041 get_tok_str(v
, NULL
));
7043 size
= type_size(&type1
, &align
);
7045 if (align
< ad
.aligned
)
7047 } else if (ad
.packed
) {
7049 } else if (*tcc_state
->pack_stack_ptr
) {
7050 if (align
> *tcc_state
->pack_stack_ptr
)
7051 align
= *tcc_state
->pack_stack_ptr
;
7054 if (bit_size
>= 0) {
7055 bt
= type1
.t
& VT_BTYPE
;
7062 error("bitfields must have scalar type");
7064 if (bit_size
> bsize
) {
7065 error("width of '%s' exceeds its type",
7066 get_tok_str(v
, NULL
));
7067 } else if (bit_size
== bsize
) {
7068 /* no need for bit fields */
7070 } else if (bit_size
== 0) {
7071 /* XXX: what to do if only padding in a
7073 /* zero size: means to pad */
7076 /* we do not have enough room ?
7077 did the type change?
7079 if ((bit_pos
+ bit_size
) > bsize
||
7080 bt
!= prevbt
|| a
== TOK_UNION
)
7083 /* XXX: handle LSB first */
7084 type1
.t
|= VT_BITFIELD
|
7085 (bit_pos
<< VT_STRUCT_SHIFT
) |
7086 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
7087 bit_pos
+= bit_size
;
7093 if (v
!= 0 || (type1
.t
& VT_BTYPE
) == VT_STRUCT
) {
7094 /* add new memory data only if starting
7096 if (lbit_pos
== 0) {
7097 if (a
== TOK_STRUCT
) {
7098 c
= (c
+ align
- 1) & -align
;
7107 if (align
> maxalign
)
7111 printf("add field %s offset=%d",
7112 get_tok_str(v
, NULL
), offset
);
7113 if (type1
.t
& VT_BITFIELD
) {
7114 printf(" pos=%d size=%d",
7115 (type1
.t
>> VT_STRUCT_SHIFT
) & 0x3f,
7116 (type1
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
7121 if (v
== 0 && (type1
.t
& VT_BTYPE
) == VT_STRUCT
) {
7123 while ((ass
= ass
->next
) != NULL
) {
7124 ss
= sym_push(ass
->v
, &ass
->type
, 0, offset
+ ass
->c
);
7129 ss
= sym_push(v
| SYM_FIELD
, &type1
, 0, offset
);
7133 if (tok
== ';' || tok
== TOK_EOF
)
7140 /* store size and alignment */
7141 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
7147 /* return 0 if no type declaration. otherwise, return the basic type
7150 static int parse_btype(CType
*type
, AttributeDef
*ad
)
7152 int t
, u
, type_found
, typespec_found
, typedef_found
;
7156 memset(ad
, 0, sizeof(AttributeDef
));
7164 /* currently, we really ignore extension */
7174 if ((t
& VT_BTYPE
) != 0)
7175 error("too many basic types");
7191 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
7192 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
7193 } else if ((t
& VT_BTYPE
) == VT_LONG
) {
7194 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
7208 if ((t
& VT_BTYPE
) == VT_LONG
) {
7209 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
7216 struct_decl(&type1
, VT_ENUM
);
7219 type
->ref
= type1
.ref
;
7223 struct_decl(&type1
, VT_STRUCT
);
7226 /* type modifiers */
7279 /* GNUC attribute */
7280 case TOK_ATTRIBUTE1
:
7281 case TOK_ATTRIBUTE2
:
7282 parse_attribute(ad
);
7289 parse_expr_type(&type1
);
7292 if (typespec_found
|| typedef_found
)
7295 if (!s
|| !(s
->type
.t
& VT_TYPEDEF
))
7298 t
|= (s
->type
.t
& ~VT_TYPEDEF
);
7299 type
->ref
= s
->type
.ref
;
7307 if ((t
& (VT_SIGNED
|VT_UNSIGNED
)) == (VT_SIGNED
|VT_UNSIGNED
))
7308 error("signed and unsigned modifier");
7309 if (tcc_state
->char_is_unsigned
) {
7310 if ((t
& (VT_SIGNED
|VT_UNSIGNED
|VT_BTYPE
)) == VT_BYTE
)
7315 /* long is never used as type */
7316 if ((t
& VT_BTYPE
) == VT_LONG
)
7317 #ifndef TCC_TARGET_X86_64
7318 t
= (t
& ~VT_BTYPE
) | VT_INT
;
7320 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
7326 /* convert a function parameter type (array to pointer and function to
7327 function pointer) */
7328 static inline void convert_parameter_type(CType
*pt
)
7330 /* remove const and volatile qualifiers (XXX: const could be used
7331 to indicate a const function parameter */
7332 pt
->t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7333 /* array must be transformed to pointer according to ANSI C */
7335 if ((pt
->t
& VT_BTYPE
) == VT_FUNC
) {
7340 static void post_type(CType
*type
, AttributeDef
*ad
)
7342 int n
, l
, t1
, arg_size
, align
;
7343 Sym
**plast
, *s
, *first
;
7348 /* function declaration */
7356 /* read param name and compute offset */
7357 if (l
!= FUNC_OLD
) {
7358 if (!parse_btype(&pt
, &ad1
)) {
7360 error("invalid type");
7367 if ((pt
.t
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
7369 type_decl(&pt
, &ad1
, &n
, TYPE_DIRECT
| TYPE_ABSTRACT
);
7370 if ((pt
.t
& VT_BTYPE
) == VT_VOID
)
7371 error("parameter declared as void");
7372 arg_size
+= (type_size(&pt
, &align
) + 3) & ~3;
7377 expect("identifier");
7381 convert_parameter_type(&pt
);
7382 s
= sym_push(n
| SYM_FIELD
, &pt
, 0, 0);
7388 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
7395 /* if no parameters, then old type prototype */
7399 t1
= type
->t
& VT_STORAGE
;
7400 /* NOTE: const is ignored in returned type as it has a special
7401 meaning in gcc / C++ */
7402 type
->t
&= ~(VT_STORAGE
| VT_CONSTANT
);
7403 post_type(type
, ad
);
7404 /* we push a anonymous symbol which will contain the function prototype */
7405 FUNC_ARGS(ad
->func_attr
) = arg_size
;
7406 s
= sym_push(SYM_FIELD
, type
, ad
->func_attr
, l
);
7408 type
->t
= t1
| VT_FUNC
;
7410 } else if (tok
== '[') {
7411 /* array definition */
7413 if (tok
== TOK_RESTRICT1
)
7419 error("invalid array size");
7422 /* parse next post type */
7423 t1
= type
->t
& VT_STORAGE
;
7424 type
->t
&= ~VT_STORAGE
;
7425 post_type(type
, ad
);
7427 /* we push a anonymous symbol which will contain the array
7429 s
= sym_push(SYM_FIELD
, type
, 0, n
);
7430 type
->t
= t1
| VT_ARRAY
| VT_PTR
;
7435 /* Parse a type declaration (except basic type), and return the type
7436 in 'type'. 'td' is a bitmask indicating which kind of type decl is
7437 expected. 'type' should contain the basic type. 'ad' is the
7438 attribute definition of the basic type. It can be modified by
7441 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
)
7444 CType type1
, *type2
;
7447 while (tok
== '*') {
7455 qualifiers
|= VT_CONSTANT
;
7460 qualifiers
|= VT_VOLATILE
;
7468 type
->t
|= qualifiers
;
7471 /* XXX: clarify attribute handling */
7472 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7473 parse_attribute(ad
);
7475 /* recursive type */
7476 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7477 type1
.t
= 0; /* XXX: same as int */
7480 /* XXX: this is not correct to modify 'ad' at this point, but
7481 the syntax is not clear */
7482 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7483 parse_attribute(ad
);
7484 type_decl(&type1
, ad
, v
, td
);
7487 /* type identifier */
7488 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
7492 if (!(td
& TYPE_ABSTRACT
))
7493 expect("identifier");
7497 post_type(type
, ad
);
7498 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7499 parse_attribute(ad
);
7502 /* append type at the end of type1 */
7515 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7516 static int lvalue_type(int t
)
7521 if (bt
== VT_BYTE
|| bt
== VT_BOOL
)
7523 else if (bt
== VT_SHORT
)
7527 if (t
& VT_UNSIGNED
)
7528 r
|= VT_LVAL_UNSIGNED
;
7532 /* indirection with full error checking and bound check */
7533 static void indir(void)
7535 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
) {
7536 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FUNC
)
7540 if ((vtop
->r
& VT_LVAL
) && !nocode_wanted
)
7542 vtop
->type
= *pointed_type(&vtop
->type
);
7543 /* Arrays and functions are never lvalues */
7544 if (!(vtop
->type
.t
& VT_ARRAY
)
7545 && (vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
) {
7546 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7547 /* if bound checking, the referenced pointer must be checked */
7548 if (do_bounds_check
)
7549 vtop
->r
|= VT_MUSTBOUND
;
7553 /* pass a parameter to a function and do type checking and casting */
7554 static void gfunc_param_typed(Sym
*func
, Sym
*arg
)
7559 func_type
= func
->c
;
7560 if (func_type
== FUNC_OLD
||
7561 (func_type
== FUNC_ELLIPSIS
&& arg
== NULL
)) {
7562 /* default casting : only need to convert float to double */
7563 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FLOAT
) {
7567 } else if (arg
== NULL
) {
7568 error("too many arguments to function");
7571 type
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
7572 gen_assign_cast(&type
);
7576 /* parse an expression of the form '(type)' or '(expr)' and return its
7578 static void parse_expr_type(CType
*type
)
7584 if (parse_btype(type
, &ad
)) {
7585 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7592 static void parse_type(CType
*type
)
7597 if (!parse_btype(type
, &ad
)) {
7600 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7603 static void vpush_tokc(int t
)
7607 vsetc(&type
, VT_CONST
, &tokc
);
7610 static void unary(void)
7612 int n
, t
, align
, size
, r
;
7617 /* XXX: GCC 2.95.3 does not generate a table although it should be
7631 vpush_tokc(VT_INT
| VT_UNSIGNED
);
7635 vpush_tokc(VT_LLONG
);
7639 vpush_tokc(VT_LLONG
| VT_UNSIGNED
);
7643 vpush_tokc(VT_FLOAT
);
7647 vpush_tokc(VT_DOUBLE
);
7651 vpush_tokc(VT_LDOUBLE
);
7654 case TOK___FUNCTION__
:
7656 goto tok_identifier
;
7662 /* special function name identifier */
7663 len
= strlen(funcname
) + 1;
7664 /* generate char[len] type */
7669 vpush_ref(&type
, data_section
, data_section
->data_offset
, len
);
7670 ptr
= section_ptr_add(data_section
, len
);
7671 memcpy(ptr
, funcname
, len
);
7676 #ifdef TCC_TARGET_PE
7677 t
= VT_SHORT
| VT_UNSIGNED
;
7683 /* string parsing */
7686 if (tcc_state
->warn_write_strings
)
7691 memset(&ad
, 0, sizeof(AttributeDef
));
7692 decl_initializer_alloc(&type
, &ad
, VT_CONST
, 2, 0, 0);
7697 if (parse_btype(&type
, &ad
)) {
7698 type_decl(&type
, &ad
, &n
, TYPE_ABSTRACT
);
7700 /* check ISOC99 compound literal */
7702 /* data is allocated locally by default */
7707 /* all except arrays are lvalues */
7708 if (!(type
.t
& VT_ARRAY
))
7709 r
|= lvalue_type(type
.t
);
7710 memset(&ad
, 0, sizeof(AttributeDef
));
7711 decl_initializer_alloc(&type
, &ad
, r
, 1, 0, 0);
7716 } else if (tok
== '{') {
7717 /* save all registers */
7719 /* statement expression : we do not accept break/continue
7720 inside as GCC does */
7721 block(NULL
, NULL
, NULL
, NULL
, 0, 1);
7736 /* functions names must be treated as function pointers,
7737 except for unary '&' and sizeof. Since we consider that
7738 functions are not lvalues, we only have to handle it
7739 there and in function calls. */
7740 /* arrays can also be used although they are not lvalues */
7741 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
&&
7742 !(vtop
->type
.t
& VT_ARRAY
) && !(vtop
->type
.t
& VT_LLOCAL
))
7744 mk_pointer(&vtop
->type
);
7750 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
7752 boolean
.t
= VT_BOOL
;
7754 vtop
->c
.i
= !vtop
->c
.i
;
7755 } else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
7756 vtop
->c
.i
= vtop
->c
.i
^ 1;
7759 vseti(VT_JMP
, gtst(1, 0));
7770 /* in order to force cast, we add zero */
7772 if ((vtop
->type
.t
& VT_BTYPE
) == VT_PTR
)
7773 error("pointer not accepted for unary plus");
7783 parse_expr_type(&type
);
7787 size
= type_size(&type
, &align
);
7788 if (t
== TOK_SIZEOF
) {
7790 error("sizeof applied to an incomplete type");
7795 vtop
->type
.t
|= VT_UNSIGNED
;
7798 case TOK_builtin_types_compatible_p
:
7807 type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7808 type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7809 vpushi(is_compatible_types(&type1
, &type2
));
7812 case TOK_builtin_constant_p
:
7814 int saved_nocode_wanted
, res
;
7817 saved_nocode_wanted
= nocode_wanted
;
7820 res
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
7822 nocode_wanted
= saved_nocode_wanted
;
7827 case TOK_builtin_frame_address
:
7832 if (tok
!= TOK_CINT
) {
7833 error("__builtin_frame_address only takes integers");
7836 error("TCC only supports __builtin_frame_address(0)");
7842 vset(&type
, VT_LOCAL
, 0);
7845 #ifdef TCC_TARGET_X86_64
7846 case TOK_builtin_malloc
:
7848 goto tok_identifier
;
7849 case TOK_builtin_free
:
7851 goto tok_identifier
;
7868 goto tok_identifier
;
7870 /* allow to take the address of a label */
7871 if (tok
< TOK_UIDENT
)
7872 expect("label identifier");
7873 s
= label_find(tok
);
7875 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
7877 if (s
->r
== LABEL_DECLARED
)
7878 s
->r
= LABEL_FORWARD
;
7881 s
->type
.t
= VT_VOID
;
7882 mk_pointer(&s
->type
);
7883 s
->type
.t
|= VT_STATIC
;
7885 vset(&s
->type
, VT_CONST
| VT_SYM
, 0);
7894 expect("identifier");
7898 error("'%s' undeclared", get_tok_str(t
, NULL
));
7899 /* for simple function calls, we tolerate undeclared
7900 external reference to int() function */
7901 if (tcc_state
->warn_implicit_function_declaration
)
7902 warning("implicit declaration of function '%s'",
7903 get_tok_str(t
, NULL
));
7904 s
= external_global_sym(t
, &func_old_type
, 0);
7906 if ((s
->type
.t
& (VT_STATIC
| VT_INLINE
| VT_BTYPE
)) ==
7907 (VT_STATIC
| VT_INLINE
| VT_FUNC
)) {
7908 /* if referencing an inline function, then we generate a
7909 symbol to it if not already done. It will have the
7910 effect to generate code for it at the end of the
7911 compilation unit. Inline function as always
7912 generated in the text section. */
7914 put_extern_sym(s
, text_section
, 0, 0);
7915 r
= VT_SYM
| VT_CONST
;
7919 vset(&s
->type
, r
, s
->c
);
7920 /* if forward reference, we must point to s */
7921 if (vtop
->r
& VT_SYM
) {
7928 /* post operations */
7930 if (tok
== TOK_INC
|| tok
== TOK_DEC
) {
7933 } else if (tok
== '.' || tok
== TOK_ARROW
) {
7935 if (tok
== TOK_ARROW
)
7940 /* expect pointer on structure */
7941 if ((vtop
->type
.t
& VT_BTYPE
) != VT_STRUCT
)
7942 expect("struct or union");
7946 while ((s
= s
->next
) != NULL
) {
7951 error("field not found: %s", get_tok_str(tok
& ~SYM_FIELD
, NULL
));
7952 /* add field offset to pointer */
7953 vtop
->type
= char_pointer_type
; /* change type to 'char *' */
7956 /* change type to field type, and set to lvalue */
7957 vtop
->type
= s
->type
;
7958 /* an array is never an lvalue */
7959 if (!(vtop
->type
.t
& VT_ARRAY
)) {
7960 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7961 /* if bound checking, the referenced pointer must be checked */
7962 if (do_bounds_check
)
7963 vtop
->r
|= VT_MUSTBOUND
;
7966 } else if (tok
== '[') {
7972 } else if (tok
== '(') {
7978 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
) {
7979 /* pointer test (no array accepted) */
7980 if ((vtop
->type
.t
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
7981 vtop
->type
= *pointed_type(&vtop
->type
);
7982 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
)
7986 expect("function pointer");
7989 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
7991 /* get return type */
7994 sa
= s
->next
; /* first parameter */
7997 /* compute first implicit argument if a structure is returned */
7998 if ((s
->type
.t
& VT_BTYPE
) == VT_STRUCT
) {
7999 /* get some space for the returned structure */
8000 size
= type_size(&s
->type
, &align
);
8001 loc
= (loc
- size
) & -align
;
8003 ret
.r
= VT_LOCAL
| VT_LVAL
;
8004 /* pass it as 'int' to avoid structure arg passing
8006 vseti(VT_LOCAL
, loc
);
8011 /* return in register */
8012 if (is_float(ret
.type
.t
)) {
8013 ret
.r
= reg_fret(ret
.type
.t
);
8015 if ((ret
.type
.t
& VT_BTYPE
) == VT_LLONG
)
8024 gfunc_param_typed(s
, sa
);
8034 error("too few arguments to function");
8036 if (!nocode_wanted
) {
8037 gfunc_call(nb_args
);
8039 vtop
-= (nb_args
+ 1);
8042 vsetc(&ret
.type
, ret
.r
, &ret
.c
);
8050 static void uneq(void)
8056 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
8057 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
8058 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
8073 static void expr_prod(void)
8078 while (tok
== '*' || tok
== '/' || tok
== '%') {
8086 static void expr_sum(void)
8091 while (tok
== '+' || tok
== '-') {
8099 static void expr_shift(void)
8104 while (tok
== TOK_SHL
|| tok
== TOK_SAR
) {
8112 static void expr_cmp(void)
8117 while ((tok
>= TOK_ULE
&& tok
<= TOK_GT
) ||
8118 tok
== TOK_ULT
|| tok
== TOK_UGE
) {
8126 static void expr_cmpeq(void)
8131 while (tok
== TOK_EQ
|| tok
== TOK_NE
) {
8139 static void expr_and(void)
8142 while (tok
== '&') {
8149 static void expr_xor(void)
8152 while (tok
== '^') {
8159 static void expr_or(void)
8162 while (tok
== '|') {
8169 /* XXX: fix this mess */
8170 static void expr_land_const(void)
8173 while (tok
== TOK_LAND
) {
8180 /* XXX: fix this mess */
8181 static void expr_lor_const(void)
8184 while (tok
== TOK_LOR
) {
8191 /* only used if non constant */
8192 static void expr_land(void)
8197 if (tok
== TOK_LAND
) {
8202 if (tok
!= TOK_LAND
) {
8212 static void expr_lor(void)
8217 if (tok
== TOK_LOR
) {
8222 if (tok
!= TOK_LOR
) {
8232 /* XXX: better constant handling */
8233 static void expr_eq(void)
8235 int tt
, u
, r1
, r2
, rc
, t1
, t2
, bt1
, bt2
;
8237 CType type
, type1
, type2
;
8244 boolean
.t
= VT_BOOL
;
8250 if (tok
!= ':' || !gnu_ext
) {
8265 if (vtop
!= vstack
) {
8266 /* needed to avoid having different registers saved in
8268 if (is_float(vtop
->type
.t
)) {
8270 #ifdef TCC_TARGET_X86_64
8271 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LDOUBLE
) {
8281 if (tok
== ':' && gnu_ext
) {
8289 sv
= *vtop
; /* save value to handle it later */
8290 vtop
--; /* no vpop so that FP stack is not flushed */
8298 bt1
= t1
& VT_BTYPE
;
8300 bt2
= t2
& VT_BTYPE
;
8301 /* cast operands to correct type according to ISOC rules */
8302 if (is_float(bt1
) || is_float(bt2
)) {
8303 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
8304 type
.t
= VT_LDOUBLE
;
8305 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
8310 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
8311 /* cast to biggest op */
8313 /* convert to unsigned if it does not fit in a long long */
8314 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
8315 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
8316 type
.t
|= VT_UNSIGNED
;
8317 } else if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
8318 /* XXX: test pointer compatibility */
8320 } else if (bt1
== VT_FUNC
|| bt2
== VT_FUNC
) {
8321 /* XXX: test function pointer compatibility */
8323 } else if (bt1
== VT_STRUCT
|| bt2
== VT_STRUCT
) {
8324 /* XXX: test structure compatibility */
8326 } else if (bt1
== VT_VOID
|| bt2
== VT_VOID
) {
8327 /* NOTE: as an extension, we accept void on only one side */
8330 /* integer operations */
8332 /* convert to unsigned if it does not fit in an integer */
8333 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
8334 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
8335 type
.t
|= VT_UNSIGNED
;
8338 /* now we convert second operand */
8340 if (VT_STRUCT
== (vtop
->type
.t
& VT_BTYPE
))
8343 if (is_float(type
.t
)) {
8345 #ifdef TCC_TARGET_X86_64
8346 if ((type
.t
& VT_BTYPE
) == VT_LDOUBLE
) {
8350 } else if ((type
.t
& VT_BTYPE
) == VT_LLONG
) {
8351 /* for long longs, we use fixed registers to avoid having
8352 to handle a complicated move */
8357 /* this is horrible, but we must also convert first
8361 /* put again first value and cast it */
8364 if (VT_STRUCT
== (vtop
->type
.t
& VT_BTYPE
))
8374 static void gexpr(void)
8385 /* parse an expression and return its type without any side effect. */
8386 static void expr_type(CType
*type
)
8388 int saved_nocode_wanted
;
8390 saved_nocode_wanted
= nocode_wanted
;
8395 nocode_wanted
= saved_nocode_wanted
;
8398 /* parse a unary expression and return its type without any side
8400 static void unary_type(CType
*type
)
8412 /* parse a constant expression and return value in vtop. */
8413 static void expr_const1(void)
8422 /* parse an integer constant and return its value. */
8423 static int expr_const(void)
8427 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
8428 expect("constant expression");
8434 /* return the label token if current token is a label, otherwise
8436 static int is_label(void)
8440 /* fast test first */
8441 if (tok
< TOK_UIDENT
)
8443 /* no need to save tokc because tok is an identifier */
8450 unget_tok(last_tok
);
8455 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
8456 int case_reg
, int is_expr
)
8461 /* generate line number info */
8463 (last_line_num
!= file
->line_num
|| last_ind
!= ind
)) {
8464 put_stabn(N_SLINE
, 0, file
->line_num
, ind
- func_ind
);
8466 last_line_num
= file
->line_num
;
8470 /* default return value is (void) */
8472 vtop
->type
.t
= VT_VOID
;
8475 if (tok
== TOK_IF
) {
8482 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
8484 if (c
== TOK_ELSE
) {
8488 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
8489 gsym(d
); /* patch else jmp */
8492 } else if (tok
== TOK_WHILE
) {
8500 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8504 } else if (tok
== '{') {
8508 /* record local declaration stack position */
8510 llabel
= local_label_stack
;
8511 /* handle local labels declarations */
8512 if (tok
== TOK_LABEL
) {
8515 if (tok
< TOK_UIDENT
)
8516 expect("label identifier");
8517 label_push(&local_label_stack
, tok
, LABEL_DECLARED
);
8527 while (tok
!= '}') {
8532 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
8535 /* pop locally defined labels */
8536 label_pop(&local_label_stack
, llabel
);
8537 /* pop locally defined symbols */
8539 /* XXX: this solution makes only valgrind happy...
8540 triggered by gcc.c-torture/execute/20000917-1.c */
8542 switch(vtop
->type
.t
& VT_BTYPE
) {
8547 for(p
=vtop
->type
.ref
;p
;p
=p
->prev
)
8549 error("unsupported expression type");
8552 sym_pop(&local_stack
, s
);
8554 } else if (tok
== TOK_RETURN
) {
8558 gen_assign_cast(&func_vt
);
8559 if ((func_vt
.t
& VT_BTYPE
) == VT_STRUCT
) {
8561 /* if returning structure, must copy it to implicit
8562 first pointer arg location */
8565 size
= type_size(&func_vt
,&align
);
8568 if((vtop
->r
!= (VT_LOCAL
| VT_LVAL
) || (vtop
->c
.i
& 3))
8572 loc
= (loc
- size
) & -4;
8575 vset(&type
, VT_LOCAL
| VT_LVAL
, addr
);
8578 vset(&int_type
, VT_LOCAL
| VT_LVAL
, addr
);
8580 vtop
->type
= int_type
;
8586 vset(&type
, VT_LOCAL
| VT_LVAL
, func_vc
);
8589 /* copy structure value to pointer */
8594 } else if (is_float(func_vt
.t
)) {
8595 gv(rc_fret(func_vt
.t
));
8599 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
8602 rsym
= gjmp(rsym
); /* jmp */
8603 } else if (tok
== TOK_BREAK
) {
8606 error("cannot break");
8607 *bsym
= gjmp(*bsym
);
8610 } else if (tok
== TOK_CONTINUE
) {
8613 error("cannot continue");
8614 *csym
= gjmp(*csym
);
8617 } else if (tok
== TOK_FOR
) {
8644 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8649 if (tok
== TOK_DO
) {
8654 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8665 if (tok
== TOK_SWITCH
) {
8669 /* XXX: other types than integer */
8670 case_reg
= gv(RC_INT
);
8674 b
= gjmp(0); /* jump to first case */
8676 block(&a
, csym
, &b
, &c
, case_reg
, 0);
8677 /* if no default, jmp after switch */
8685 if (tok
== TOK_CASE
) {
8692 if (gnu_ext
&& tok
== TOK_DOTS
) {
8696 warning("empty case range");
8698 /* since a case is like a label, we must skip it with a jmp */
8705 *case_sym
= gtst(1, 0);
8708 *case_sym
= gtst(1, 0);
8712 *case_sym
= gtst(1, *case_sym
);
8717 goto block_after_label
;
8719 if (tok
== TOK_DEFAULT
) {
8725 error("too many 'default'");
8728 goto block_after_label
;
8730 if (tok
== TOK_GOTO
) {
8732 if (tok
== '*' && gnu_ext
) {
8736 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
8739 } else if (tok
>= TOK_UIDENT
) {
8740 s
= label_find(tok
);
8741 /* put forward definition if needed */
8743 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
8745 if (s
->r
== LABEL_DECLARED
)
8746 s
->r
= LABEL_FORWARD
;
8748 /* label already defined */
8749 if (s
->r
& LABEL_FORWARD
)
8750 s
->next
= (void *)gjmp((long)s
->next
);
8752 gjmp_addr((long)s
->next
);
8755 expect("label identifier");
8758 } else if (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
) {
8766 if (s
->r
== LABEL_DEFINED
)
8767 error("duplicate label '%s'", get_tok_str(s
->v
, NULL
));
8768 gsym((long)s
->next
);
8769 s
->r
= LABEL_DEFINED
;
8771 s
= label_push(&global_label_stack
, b
, LABEL_DEFINED
);
8773 s
->next
= (void *)ind
;
8774 /* we accept this, but it is a mistake */
8777 warning("deprecated use of label at end of compound statement");
8781 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
8784 /* expression case */
8799 /* t is the array or struct type. c is the array or struct
8800 address. cur_index/cur_field is the pointer to the current
8801 value. 'size_only' is true if only size info is needed (only used
8803 static void decl_designator(CType
*type
, Section
*sec
, unsigned long c
,
8804 int *cur_index
, Sym
**cur_field
,
8808 int notfirst
, index
, index_last
, align
, l
, nb_elems
, elem_size
;
8814 if (gnu_ext
&& (l
= is_label()) != 0)
8816 while (tok
== '[' || tok
== '.') {
8818 if (!(type
->t
& VT_ARRAY
))
8819 expect("array type");
8822 index
= expr_const();
8823 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
8824 expect("invalid index");
8825 if (tok
== TOK_DOTS
&& gnu_ext
) {
8827 index_last
= expr_const();
8828 if (index_last
< 0 ||
8829 (s
->c
>= 0 && index_last
>= s
->c
) ||
8831 expect("invalid index");
8837 *cur_index
= index_last
;
8838 type
= pointed_type(type
);
8839 elem_size
= type_size(type
, &align
);
8840 c
+= index
* elem_size
;
8841 /* NOTE: we only support ranges for last designator */
8842 nb_elems
= index_last
- index
+ 1;
8843 if (nb_elems
!= 1) {
8852 if ((type
->t
& VT_BTYPE
) != VT_STRUCT
)
8853 expect("struct/union type");
8866 /* XXX: fix this mess by using explicit storage field */
8868 type1
.t
|= (type
->t
& ~VT_TYPE
);
8882 if (type
->t
& VT_ARRAY
) {
8884 type
= pointed_type(type
);
8885 c
+= index
* type_size(type
, &align
);
8889 error("too many field init");
8890 /* XXX: fix this mess by using explicit storage field */
8892 type1
.t
|= (type
->t
& ~VT_TYPE
);
8897 decl_initializer(type
, sec
, c
, 0, size_only
);
8899 /* XXX: make it more general */
8900 if (!size_only
&& nb_elems
> 1) {
8901 unsigned long c_end
;
8906 error("range init not supported yet for dynamic storage");
8907 c_end
= c
+ nb_elems
* elem_size
;
8908 if (c_end
> sec
->data_allocated
)
8909 section_realloc(sec
, c_end
);
8910 src
= sec
->data
+ c
;
8912 for(i
= 1; i
< nb_elems
; i
++) {
8914 memcpy(dst
, src
, elem_size
);
8920 #define EXPR_CONST 1
8923 /* store a value or an expression directly in global data or in local array */
8924 static void init_putv(CType
*type
, Section
*sec
, unsigned long c
,
8925 int v
, int expr_type
)
8927 int saved_global_expr
, bt
, bit_pos
, bit_size
;
8929 unsigned long long bit_mask
;
8937 /* compound literals must be allocated globally in this case */
8938 saved_global_expr
= global_expr
;
8941 global_expr
= saved_global_expr
;
8942 /* NOTE: symbols are accepted */
8943 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) != VT_CONST
)
8944 error("initializer element is not constant");
8952 dtype
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
8955 /* XXX: not portable */
8956 /* XXX: generate error if incorrect relocation */
8957 gen_assign_cast(&dtype
);
8958 bt
= type
->t
& VT_BTYPE
;
8959 /* we'll write at most 12 bytes */
8960 if (c
+ 12 > sec
->data_allocated
) {
8961 section_realloc(sec
, c
+ 12);
8963 ptr
= sec
->data
+ c
;
8964 /* XXX: make code faster ? */
8965 if (!(type
->t
& VT_BITFIELD
)) {
8970 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
8971 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
8972 bit_mask
= (1LL << bit_size
) - 1;
8974 if ((vtop
->r
& VT_SYM
) &&
8980 (bt
== VT_INT
&& bit_size
!= 32)))
8981 error("initializer element is not computable at load time");
8984 vtop
->c
.i
= (vtop
->c
.i
!= 0);
8986 *(char *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8989 *(short *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8992 *(double *)ptr
= vtop
->c
.d
;
8995 *(long double *)ptr
= vtop
->c
.ld
;
8998 *(long long *)ptr
|= (vtop
->c
.ll
& bit_mask
) << bit_pos
;
9001 if (vtop
->r
& VT_SYM
) {
9002 greloc(sec
, vtop
->sym
, c
, R_DATA_32
);
9004 *(int *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
9009 vset(&dtype
, VT_LOCAL
|VT_LVAL
, c
);
9016 /* put zeros for variable based init */
9017 static void init_putz(CType
*t
, Section
*sec
, unsigned long c
, int size
)
9020 /* nothing to do because globals are already set to zero */
9022 vpush_global_sym(&func_old_type
, TOK_memset
);
9030 /* 't' contains the type and storage info. 'c' is the offset of the
9031 object in section 'sec'. If 'sec' is NULL, it means stack based
9032 allocation. 'first' is true if array '{' must be read (multi
9033 dimension implicit array init handling). 'size_only' is true if
9034 size only evaluation is wanted (only for arrays). */
9035 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
9036 int first
, int size_only
)
9038 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
9039 int size1
, align1
, expr_type
;
9043 if (type
->t
& VT_ARRAY
) {
9047 t1
= pointed_type(type
);
9048 size1
= type_size(t1
, &align1
);
9051 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
9057 /* only parse strings here if correct type (otherwise: handle
9058 them as ((w)char *) expressions */
9059 if ((tok
== TOK_LSTR
&&
9060 #ifdef TCC_TARGET_PE
9061 (t1
->t
& VT_BTYPE
) == VT_SHORT
&& (t1
->t
& VT_UNSIGNED
)
9063 (t1
->t
& VT_BTYPE
) == VT_INT
9065 ) || (tok
== TOK_STR
&& (t1
->t
& VT_BTYPE
) == VT_BYTE
)) {
9066 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
9071 /* compute maximum number of chars wanted */
9073 cstr_len
= cstr
->size
;
9075 cstr_len
= cstr
->size
/ sizeof(nwchar_t
);
9078 if (n
>= 0 && nb
> (n
- array_length
))
9079 nb
= n
- array_length
;
9082 warning("initializer-string for array is too long");
9083 /* in order to go faster for common case (char
9084 string in global variable, we handle it
9086 if (sec
&& tok
== TOK_STR
&& size1
== 1) {
9087 memcpy(sec
->data
+ c
+ array_length
, cstr
->data
, nb
);
9091 ch
= ((unsigned char *)cstr
->data
)[i
];
9093 ch
= ((nwchar_t
*)cstr
->data
)[i
];
9094 init_putv(t1
, sec
, c
+ (array_length
+ i
) * size1
,
9102 /* only add trailing zero if enough storage (no
9103 warning in this case since it is standard) */
9104 if (n
< 0 || array_length
< n
) {
9106 init_putv(t1
, sec
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
9112 while (tok
!= '}') {
9113 decl_designator(type
, sec
, c
, &index
, NULL
, size_only
);
9114 if (n
>= 0 && index
>= n
)
9115 error("index too large");
9116 /* must put zero in holes (note that doing it that way
9117 ensures that it even works with designators) */
9118 if (!size_only
&& array_length
< index
) {
9119 init_putz(t1
, sec
, c
+ array_length
* size1
,
9120 (index
- array_length
) * size1
);
9123 if (index
> array_length
)
9124 array_length
= index
;
9125 /* special test for multi dimensional arrays (may not
9126 be strictly correct if designators are used at the
9128 if (index
>= n
&& no_oblock
)
9137 /* put zeros at the end */
9138 if (!size_only
&& n
>= 0 && array_length
< n
) {
9139 init_putz(t1
, sec
, c
+ array_length
* size1
,
9140 (n
- array_length
) * size1
);
9142 /* patch type size if needed */
9144 s
->c
= array_length
;
9145 } else if ((type
->t
& VT_BTYPE
) == VT_STRUCT
&&
9146 (sec
|| !first
|| tok
== '{')) {
9149 /* NOTE: the previous test is a specific case for automatic
9150 struct/union init */
9151 /* XXX: union needs only one init */
9153 /* XXX: this test is incorrect for local initializers
9154 beginning with ( without {. It would be much more difficult
9155 to do it correctly (ideally, the expression parser should
9156 be used in all cases) */
9162 while (tok
== '(') {
9166 if (!parse_btype(&type1
, &ad1
))
9168 type_decl(&type1
, &ad1
, &n
, TYPE_ABSTRACT
);
9170 if (!is_assignable_types(type
, &type1
))
9171 error("invalid type for cast");
9176 if (first
|| tok
== '{') {
9185 while (tok
!= '}') {
9186 decl_designator(type
, sec
, c
, NULL
, &f
, size_only
);
9188 if (!size_only
&& array_length
< index
) {
9189 init_putz(type
, sec
, c
+ array_length
,
9190 index
- array_length
);
9192 index
= index
+ type_size(&f
->type
, &align1
);
9193 if (index
> array_length
)
9194 array_length
= index
;
9196 if (no_oblock
&& f
== NULL
)
9202 /* put zeros at the end */
9203 if (!size_only
&& array_length
< n
) {
9204 init_putz(type
, sec
, c
+ array_length
,
9213 } else if (tok
== '{') {
9215 decl_initializer(type
, sec
, c
, first
, size_only
);
9217 } else if (size_only
) {
9218 /* just skip expression */
9220 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
9224 else if (tok
== ')')
9229 /* currently, we always use constant expression for globals
9230 (may change for scripting case) */
9231 expr_type
= EXPR_CONST
;
9233 expr_type
= EXPR_ANY
;
9234 init_putv(type
, sec
, c
, 0, expr_type
);
9238 /* parse an initializer for type 't' if 'has_init' is non zero, and
9239 allocate space in local or global data space ('r' is either
9240 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
9241 variable 'v' of scope 'scope' is declared before initializers are
9242 parsed. If 'v' is zero, then a reference to the new object is put
9243 in the value stack. If 'has_init' is 2, a special parsing is done
9244 to handle string constants. */
9245 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
9246 int has_init
, int v
, int scope
)
9248 int size
, align
, addr
, data_offset
;
9250 ParseState saved_parse_state
= {0};
9251 TokenString init_str
;
9254 size
= type_size(type
, &align
);
9255 /* If unknown size, we must evaluate it before
9256 evaluating initializers because
9257 initializers can generate global data too
9258 (e.g. string pointers or ISOC99 compound
9259 literals). It also simplifies local
9260 initializers handling */
9261 tok_str_new(&init_str
);
9264 error("unknown type size");
9265 /* get all init string */
9266 if (has_init
== 2) {
9267 /* only get strings */
9268 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
9269 tok_str_add_tok(&init_str
);
9274 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
9276 error("unexpected end of file in initializer");
9277 tok_str_add_tok(&init_str
);
9280 else if (tok
== '}') {
9290 tok_str_add(&init_str
, -1);
9291 tok_str_add(&init_str
, 0);
9294 save_parse_state(&saved_parse_state
);
9296 macro_ptr
= init_str
.str
;
9298 decl_initializer(type
, NULL
, 0, 1, 1);
9299 /* prepare second initializer parsing */
9300 macro_ptr
= init_str
.str
;
9303 /* if still unknown size, error */
9304 size
= type_size(type
, &align
);
9306 error("unknown type size");
9308 /* take into account specified alignment if bigger */
9310 if (ad
->aligned
> align
)
9311 align
= ad
->aligned
;
9312 } else if (ad
->packed
) {
9315 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
9317 if (do_bounds_check
&& (type
->t
& VT_ARRAY
))
9319 loc
= (loc
- size
) & -align
;
9321 /* handles bounds */
9322 /* XXX: currently, since we do only one pass, we cannot track
9323 '&' operators, so we add only arrays */
9324 if (do_bounds_check
&& (type
->t
& VT_ARRAY
)) {
9325 unsigned long *bounds_ptr
;
9326 /* add padding between regions */
9328 /* then add local bound info */
9329 bounds_ptr
= section_ptr_add(lbounds_section
, 2 * sizeof(unsigned long));
9330 bounds_ptr
[0] = addr
;
9331 bounds_ptr
[1] = size
;
9334 /* local variable */
9335 sym_push(v
, type
, r
, addr
);
9337 /* push local reference */
9338 vset(type
, r
, addr
);
9344 if (v
&& scope
== VT_CONST
) {
9345 /* see if the symbol was already defined */
9348 if (!is_compatible_types(&sym
->type
, type
))
9349 error("incompatible types for redefinition of '%s'",
9350 get_tok_str(v
, NULL
));
9351 if (sym
->type
.t
& VT_EXTERN
) {
9352 /* if the variable is extern, it was not allocated */
9353 sym
->type
.t
&= ~VT_EXTERN
;
9354 /* set array size if it was ommited in extern
9356 if ((sym
->type
.t
& VT_ARRAY
) &&
9357 sym
->type
.ref
->c
< 0 &&
9359 sym
->type
.ref
->c
= type
->ref
->c
;
9361 /* we accept several definitions of the same
9362 global variable. this is tricky, because we
9363 must play with the SHN_COMMON type of the symbol */
9364 /* XXX: should check if the variable was already
9365 initialized. It is incorrect to initialized it
9367 /* no init data, we won't add more to the symbol */
9374 /* allocate symbol in corresponding section */
9379 else if (tcc_state
->nocommon
)
9383 data_offset
= sec
->data_offset
;
9384 data_offset
= (data_offset
+ align
- 1) & -align
;
9386 /* very important to increment global pointer at this time
9387 because initializers themselves can create new initializers */
9388 data_offset
+= size
;
9389 /* add padding if bound check */
9390 if (do_bounds_check
)
9392 sec
->data_offset
= data_offset
;
9393 /* allocate section space to put the data */
9394 if (sec
->sh_type
!= SHT_NOBITS
&&
9395 data_offset
> sec
->data_allocated
)
9396 section_realloc(sec
, data_offset
);
9397 /* align section if needed */
9398 if (align
> sec
->sh_addralign
)
9399 sec
->sh_addralign
= align
;
9401 addr
= 0; /* avoid warning */
9405 if (scope
!= VT_CONST
|| !sym
) {
9406 sym
= sym_push(v
, type
, r
| VT_SYM
, 0);
9408 /* update symbol definition */
9410 put_extern_sym(sym
, sec
, addr
, size
);
9413 /* put a common area */
9414 put_extern_sym(sym
, NULL
, align
, size
);
9415 /* XXX: find a nicer way */
9416 esym
= &((ElfW(Sym
) *)symtab_section
->data
)[sym
->c
];
9417 esym
->st_shndx
= SHN_COMMON
;
9422 /* push global reference */
9423 sym
= get_sym_ref(type
, sec
, addr
, size
);
9425 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
9429 /* handles bounds now because the symbol must be defined
9430 before for the relocation */
9431 if (do_bounds_check
) {
9432 unsigned long *bounds_ptr
;
9434 greloc(bounds_section
, sym
, bounds_section
->data_offset
, R_DATA_32
);
9435 /* then add global bound info */
9436 bounds_ptr
= section_ptr_add(bounds_section
, 2 * sizeof(long));
9437 bounds_ptr
[0] = 0; /* relocated */
9438 bounds_ptr
[1] = size
;
9442 decl_initializer(type
, sec
, addr
, 1, 0);
9443 /* restore parse state if needed */
9445 tok_str_free(init_str
.str
);
9446 restore_parse_state(&saved_parse_state
);
9452 void put_func_debug(Sym
*sym
)
9457 /* XXX: we put here a dummy type */
9458 snprintf(buf
, sizeof(buf
), "%s:%c1",
9459 funcname
, sym
->type
.t
& VT_STATIC
? 'f' : 'F');
9460 put_stabs_r(buf
, N_FUN
, 0, file
->line_num
, 0,
9461 cur_text_section
, sym
->c
);
9462 /* //gr gdb wants a line at the function */
9463 put_stabn(N_SLINE
, 0, file
->line_num
, 0);
9468 /* parse an old style function declaration list */
9469 /* XXX: check multiple parameter */
9470 static void func_decl_list(Sym
*func_sym
)
9477 /* parse each declaration */
9478 while (tok
!= '{' && tok
!= ';' && tok
!= ',' && tok
!= TOK_EOF
) {
9479 if (!parse_btype(&btype
, &ad
))
9480 expect("declaration list");
9481 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
9482 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
9484 /* we accept no variable after */
9488 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
9489 /* find parameter in function parameter list */
9492 if ((s
->v
& ~SYM_FIELD
) == v
)
9496 error("declaration for parameter '%s' but no such parameter",
9497 get_tok_str(v
, NULL
));
9499 /* check that no storage specifier except 'register' was given */
9500 if (type
.t
& VT_STORAGE
)
9501 error("storage class specified for '%s'", get_tok_str(v
, NULL
));
9502 convert_parameter_type(&type
);
9503 /* we can add the type (NOTE: it could be local to the function) */
9505 /* accept other parameters */
9516 /* parse a function defined by symbol 'sym' and generate its code in
9517 'cur_text_section' */
9518 static void gen_function(Sym
*sym
)
9520 int saved_nocode_wanted
= nocode_wanted
;
9522 ind
= cur_text_section
->data_offset
;
9523 /* NOTE: we patch the symbol size later */
9524 put_extern_sym(sym
, cur_text_section
, ind
, 0);
9525 funcname
= get_tok_str(sym
->v
, NULL
);
9527 /* put debug symbol */
9529 put_func_debug(sym
);
9530 /* push a dummy symbol to enable local sym storage */
9531 sym_push2(&local_stack
, SYM_FIELD
, 0, 0);
9532 gfunc_prolog(&sym
->type
);
9534 block(NULL
, NULL
, NULL
, NULL
, 0, 0);
9537 cur_text_section
->data_offset
= ind
;
9538 label_pop(&global_label_stack
, NULL
);
9539 sym_pop(&local_stack
, NULL
); /* reset local stack */
9540 /* end of function */
9541 /* patch symbol size */
9542 ((ElfW(Sym
) *)symtab_section
->data
)[sym
->c
].st_size
=
9545 put_stabn(N_FUN
, 0, 0, ind
- func_ind
);
9547 /* It's better to crash than to generate wrong code */
9548 cur_text_section
= NULL
;
9549 funcname
= ""; /* for safety */
9550 func_vt
.t
= VT_VOID
; /* for safety */
9551 ind
= 0; /* for safety */
9552 nocode_wanted
= saved_nocode_wanted
;
9555 static void gen_inline_functions(void)
9559 int *str
, inline_generated
;
9561 /* iterate while inline function are referenced */
9563 inline_generated
= 0;
9564 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
9566 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
9567 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
9568 (VT_STATIC
| VT_INLINE
) &&
9570 /* the function was used: generate its code and
9571 convert it to a normal function */
9572 str
= INLINE_DEF(sym
->r
);
9573 sym
->r
= VT_SYM
| VT_CONST
;
9574 sym
->type
.t
&= ~VT_INLINE
;
9578 cur_text_section
= text_section
;
9580 macro_ptr
= NULL
; /* fail safe */
9583 inline_generated
= 1;
9586 if (!inline_generated
)
9590 /* free all remaining inline function tokens */
9591 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
9593 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
9594 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
9595 (VT_STATIC
| VT_INLINE
)) {
9596 //gr printf("sym %d %s\n", sym->r, get_tok_str(sym->v, NULL));
9597 if (sym
->r
== (VT_SYM
| VT_CONST
)) //gr beware!
9599 str
= INLINE_DEF(sym
->r
);
9601 sym
->r
= 0; /* fail safe */
9606 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9607 static void decl(int l
)
9615 if (!parse_btype(&btype
, &ad
)) {
9616 /* skip redundant ';' */
9617 /* XXX: find more elegant solution */
9622 if (l
== VT_CONST
&&
9623 (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
)) {
9624 /* global asm block */
9628 /* special test for old K&R protos without explicit int
9629 type. Only accepted when defining global data */
9630 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
9634 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
9635 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
9637 /* we accept no variable after */
9641 while (1) { /* iterate thru each declaration */
9643 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
9647 type_to_str(buf
, sizeof(buf
), t
, get_tok_str(v
, NULL
));
9648 printf("type = '%s'\n", buf
);
9651 if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9652 /* if old style function prototype, we accept a
9655 if (sym
->c
== FUNC_OLD
)
9656 func_decl_list(sym
);
9661 error("cannot use local functions");
9662 if ((type
.t
& VT_BTYPE
) != VT_FUNC
)
9663 expect("function definition");
9665 /* reject abstract declarators in function definition */
9667 while ((sym
= sym
->next
) != NULL
)
9668 if (!(sym
->v
& ~SYM_FIELD
))
9669 expect("identifier");
9671 /* XXX: cannot do better now: convert extern line to static inline */
9672 if ((type
.t
& (VT_EXTERN
| VT_INLINE
)) == (VT_EXTERN
| VT_INLINE
))
9673 type
.t
= (type
.t
& ~VT_EXTERN
) | VT_STATIC
;
9677 if ((sym
->type
.t
& VT_BTYPE
) != VT_FUNC
)
9679 /* specific case: if not func_call defined, we put
9680 the one of the prototype */
9681 /* XXX: should have default value */
9682 r
= sym
->type
.ref
->r
;
9683 if (FUNC_CALL(r
) != FUNC_CDECL
9684 && FUNC_CALL(type
.ref
->r
) == FUNC_CDECL
)
9685 FUNC_CALL(type
.ref
->r
) = FUNC_CALL(r
);
9687 FUNC_EXPORT(type
.ref
->r
) = 1;
9689 if (!is_compatible_types(&sym
->type
, &type
)) {
9691 error("incompatible types for redefinition of '%s'",
9692 get_tok_str(v
, NULL
));
9694 /* if symbol is already defined, then put complete type */
9697 /* put function symbol */
9698 sym
= global_identifier_push(v
, type
.t
, 0);
9699 sym
->type
.ref
= type
.ref
;
9702 /* static inline functions are just recorded as a kind
9703 of macro. Their code will be emitted at the end of
9704 the compilation unit only if they are used */
9705 if ((type
.t
& (VT_INLINE
| VT_STATIC
)) ==
9706 (VT_INLINE
| VT_STATIC
)) {
9707 TokenString func_str
;
9710 tok_str_new(&func_str
);
9716 error("unexpected end of file");
9717 tok_str_add_tok(&func_str
);
9722 } else if (t
== '}') {
9724 if (block_level
== 0)
9728 tok_str_add(&func_str
, -1);
9729 tok_str_add(&func_str
, 0);
9730 INLINE_DEF(sym
->r
) = func_str
.str
;
9732 /* compute text section */
9733 cur_text_section
= ad
.section
;
9734 if (!cur_text_section
)
9735 cur_text_section
= text_section
;
9736 sym
->r
= VT_SYM
| VT_CONST
;
9741 if (btype
.t
& VT_TYPEDEF
) {
9742 /* save typedefed type */
9743 /* XXX: test storage specifiers ? */
9744 sym
= sym_push(v
, &type
, 0, 0);
9745 sym
->type
.t
|= VT_TYPEDEF
;
9746 } else if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9747 /* external function definition */
9748 /* specific case for func_call attribute */
9750 type
.ref
->r
= ad
.func_attr
;
9751 external_sym(v
, &type
, 0);
9753 /* not lvalue if array */
9755 if (!(type
.t
& VT_ARRAY
))
9756 r
|= lvalue_type(type
.t
);
9757 has_init
= (tok
== '=');
9758 if ((btype
.t
& VT_EXTERN
) ||
9759 ((type
.t
& VT_ARRAY
) && (type
.t
& VT_STATIC
) &&
9760 !has_init
&& l
== VT_CONST
&& type
.ref
->c
< 0)) {
9761 /* external variable */
9762 /* NOTE: as GCC, uninitialized global static
9763 arrays of null size are considered as
9765 external_sym(v
, &type
, r
);
9767 type
.t
|= (btype
.t
& VT_STATIC
); /* Retain "static". */
9768 if (type
.t
& VT_STATIC
)
9774 decl_initializer_alloc(&type
, &ad
, r
,
9788 /* better than nothing, but needs extension to handle '-E' option
9790 static void preprocess_init(TCCState
*s1
)
9792 s1
->include_stack_ptr
= s1
->include_stack
;
9793 /* XXX: move that before to avoid having to initialize
9794 file->ifdef_stack_ptr ? */
9795 s1
->ifdef_stack_ptr
= s1
->ifdef_stack
;
9796 file
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
9798 /* XXX: not ANSI compliant: bound checking says error */
9800 s1
->pack_stack
[0] = 0;
9801 s1
->pack_stack_ptr
= s1
->pack_stack
;
9804 /* compile the C file opened in 'file'. Return non zero if errors. */
9805 static int tcc_compile(TCCState
*s1
)
9809 volatile int section_sym
;
9812 printf("%s: **** new file\n", file
->filename
);
9814 preprocess_init(s1
);
9816 cur_text_section
= NULL
;
9818 anon_sym
= SYM_FIRST_ANOM
;
9820 /* file info: full path + filename */
9821 section_sym
= 0; /* avoid warning */
9823 section_sym
= put_elf_sym(symtab_section
, 0, 0,
9824 ELFW(ST_INFO
)(STB_LOCAL
, STT_SECTION
), 0,
9825 text_section
->sh_num
, NULL
);
9826 getcwd(buf
, sizeof(buf
));
9828 normalize_slashes(buf
);
9830 pstrcat(buf
, sizeof(buf
), "/");
9831 put_stabs_r(buf
, N_SO
, 0, 0,
9832 text_section
->data_offset
, text_section
, section_sym
);
9833 put_stabs_r(file
->filename
, N_SO
, 0, 0,
9834 text_section
->data_offset
, text_section
, section_sym
);
9836 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9837 symbols can be safely used */
9838 put_elf_sym(symtab_section
, 0, 0,
9839 ELFW(ST_INFO
)(STB_LOCAL
, STT_FILE
), 0,
9840 SHN_ABS
, file
->filename
);
9842 /* define some often used types */
9843 int_type
.t
= VT_INT
;
9845 char_pointer_type
.t
= VT_BYTE
;
9846 mk_pointer(&char_pointer_type
);
9848 func_old_type
.t
= VT_FUNC
;
9849 func_old_type
.ref
= sym_push(SYM_FIELD
, &int_type
, FUNC_CDECL
, FUNC_OLD
);
9851 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
9852 float_type
.t
= VT_FLOAT
;
9853 double_type
.t
= VT_DOUBLE
;
9855 func_float_type
.t
= VT_FUNC
;
9856 func_float_type
.ref
= sym_push(SYM_FIELD
, &float_type
, FUNC_CDECL
, FUNC_OLD
);
9857 func_double_type
.t
= VT_FUNC
;
9858 func_double_type
.ref
= sym_push(SYM_FIELD
, &double_type
, FUNC_CDECL
, FUNC_OLD
);
9862 /* define 'void *alloca(unsigned int)' builtin function */
9867 sym
= sym_push(p
, mk_pointer(VT_VOID
), FUNC_CDECL
, FUNC_NEW
);
9868 s1
= sym_push(SYM_FIELD
, VT_UNSIGNED
| VT_INT
, 0, 0);
9871 sym_push(TOK_alloca
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), VT_CONST
, 0);
9875 define_start
= define_stack
;
9878 if (setjmp(s1
->error_jmp_buf
) == 0) {
9880 s1
->error_set_jmp_enabled
= 1;
9882 ch
= file
->buf_ptr
[0];
9883 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
9884 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
;
9888 expect("declaration");
9890 /* end of translation unit info */
9892 put_stabs_r(NULL
, N_SO
, 0, 0,
9893 text_section
->data_offset
, text_section
, section_sym
);
9896 s1
->error_set_jmp_enabled
= 0;
9898 /* reset define stack, but leave -Dsymbols (may be incorrect if
9899 they are undefined) */
9900 free_defines(define_start
);
9902 gen_inline_functions();
9904 sym_pop(&global_stack
, NULL
);
9905 sym_pop(&local_stack
, NULL
);
9907 return s1
->nb_errors
!= 0 ? -1 : 0;
9910 /* Preprocess the current file */
9911 static int tcc_preprocess(TCCState
*s1
)
9914 BufferedFile
*file_ref
;
9915 int token_seen
, line_ref
;
9917 preprocess_init(s1
);
9918 define_start
= define_stack
;
9919 ch
= file
->buf_ptr
[0];
9920 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
9921 parse_flags
= PARSE_FLAG_ASM_COMMENTS
| PARSE_FLAG_PREPROCESS
|
9922 PARSE_FLAG_LINEFEED
| PARSE_FLAG_SPACES
;
9929 if (tok
== TOK_EOF
) {
9931 } else if (tok
== TOK_LINEFEED
) {
9936 } else if (!token_seen
) {
9937 int d
= file
->line_num
- line_ref
;
9938 if (file
!= file_ref
|| d
< 0 || d
>= 8)
9939 fprintf(s1
->outfile
, "# %d \"%s\"\n", file
->line_num
, file
->filename
);
9942 fputs("\n", s1
->outfile
), --d
;
9943 line_ref
= (file_ref
= file
)->line_num
;
9946 fputs(get_tok_str(tok
, &tokc
), s1
->outfile
);
9948 free_defines(define_start
);
9953 int tcc_compile_string(TCCState
*s
, const char *str
)
9955 BufferedFile bf1
, *bf
= &bf1
;
9959 /* init file structure */
9961 /* XXX: avoid copying */
9963 buf
= tcc_malloc(len
+ 1);
9966 memcpy(buf
, str
, len
);
9969 bf
->buf_end
= buf
+ len
;
9970 pstrcpy(bf
->filename
, sizeof(bf
->filename
), "<string>");
9973 ret
= tcc_compile(s
);
9977 /* currently, no need to close */
9982 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9983 void tcc_define_symbol(TCCState
*s1
, const char *sym
, const char *value
)
9985 BufferedFile bf1
, *bf
= &bf1
;
9987 pstrcpy(bf
->buffer
, IO_BUF_SIZE
, sym
);
9988 pstrcat(bf
->buffer
, IO_BUF_SIZE
, " ");
9992 pstrcat(bf
->buffer
, IO_BUF_SIZE
, value
);
9994 /* init file structure */
9996 bf
->buf_ptr
= bf
->buffer
;
9997 bf
->buf_end
= bf
->buffer
+ strlen(bf
->buffer
);
9998 *bf
->buf_end
= CH_EOB
;
9999 bf
->filename
[0] = '\0';
10003 s1
->include_stack_ptr
= s1
->include_stack
;
10005 /* parse with define parser */
10006 ch
= file
->buf_ptr
[0];
10012 /* undefine a preprocessor symbol */
10013 void tcc_undefine_symbol(TCCState
*s1
, const char *sym
)
10017 ts
= tok_alloc(sym
, strlen(sym
));
10018 s
= define_find(ts
->tok
);
10019 /* undefine symbol by putting an invalid name */
10024 #ifdef CONFIG_TCC_ASM
10026 #ifdef TCC_TARGET_I386
10027 #include "i386-asm.c"
10029 #include "tccasm.c"
10032 static void asm_instr(void)
10034 error("inline asm() not supported");
10036 static void asm_global_instr(void)
10038 error("inline asm() not supported");
10042 #include "tccelf.c"
10044 #ifdef TCC_TARGET_COFF
10045 #include "tcccoff.c"
10048 #ifdef TCC_TARGET_PE
10052 #ifdef CONFIG_TCC_BACKTRACE
10053 /* print the position in the source file of PC value 'pc' by reading
10054 the stabs debug information */
10055 static void rt_printline(unsigned long wanted_pc
)
10057 Stab_Sym
*sym
, *sym_end
;
10058 char func_name
[128], last_func_name
[128];
10059 unsigned long func_addr
, last_pc
, pc
;
10060 const char *incl_files
[INCLUDE_STACK_SIZE
];
10061 int incl_index
, len
, last_line_num
, i
;
10062 const char *str
, *p
;
10064 fprintf(stderr
, "0x%08lx:", wanted_pc
);
10066 func_name
[0] = '\0';
10069 last_func_name
[0] = '\0';
10070 last_pc
= 0xffffffff;
10072 sym
= (Stab_Sym
*)stab_section
->data
+ 1;
10073 sym_end
= (Stab_Sym
*)(stab_section
->data
+ stab_section
->data_offset
);
10074 while (sym
< sym_end
) {
10075 switch(sym
->n_type
) {
10076 /* function start or end */
10078 if (sym
->n_strx
== 0) {
10079 /* we test if between last line and end of function */
10080 pc
= sym
->n_value
+ func_addr
;
10081 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
10083 func_name
[0] = '\0';
10086 str
= stabstr_section
->data
+ sym
->n_strx
;
10087 p
= strchr(str
, ':');
10089 pstrcpy(func_name
, sizeof(func_name
), str
);
10092 if (len
> sizeof(func_name
) - 1)
10093 len
= sizeof(func_name
) - 1;
10094 memcpy(func_name
, str
, len
);
10095 func_name
[len
] = '\0';
10097 func_addr
= sym
->n_value
;
10100 /* line number info */
10102 pc
= sym
->n_value
+ func_addr
;
10103 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
10106 last_line_num
= sym
->n_desc
;
10108 strcpy(last_func_name
, func_name
);
10110 /* include files */
10112 str
= stabstr_section
->data
+ sym
->n_strx
;
10114 if (incl_index
< INCLUDE_STACK_SIZE
) {
10115 incl_files
[incl_index
++] = str
;
10119 if (incl_index
> 1)
10123 if (sym
->n_strx
== 0) {
10124 incl_index
= 0; /* end of translation unit */
10126 str
= stabstr_section
->data
+ sym
->n_strx
;
10127 /* do not add path */
10129 if (len
> 0 && str
[len
- 1] != '/')
10137 /* second pass: we try symtab symbols (no line number info) */
10140 ElfW(Sym
) *sym
, *sym_end
;
10143 sym_end
= (ElfW(Sym
) *)(symtab_section
->data
+ symtab_section
->data_offset
);
10144 for(sym
= (ElfW(Sym
) *)symtab_section
->data
+ 1;
10147 type
= ELFW(ST_TYPE
)(sym
->st_info
);
10148 if (type
== STT_FUNC
) {
10149 if (wanted_pc
>= sym
->st_value
&&
10150 wanted_pc
< sym
->st_value
+ sym
->st_size
) {
10151 pstrcpy(last_func_name
, sizeof(last_func_name
),
10152 strtab_section
->data
+ sym
->st_name
);
10158 /* did not find any info: */
10159 fprintf(stderr
, " ???\n");
10162 if (last_func_name
[0] != '\0') {
10163 fprintf(stderr
, " %s()", last_func_name
);
10165 if (incl_index
> 0) {
10166 fprintf(stderr
, " (%s:%d",
10167 incl_files
[incl_index
- 1], last_line_num
);
10168 for(i
= incl_index
- 2; i
>= 0; i
--)
10169 fprintf(stderr
, ", included from %s", incl_files
[i
]);
10170 fprintf(stderr
, ")");
10172 fprintf(stderr
, "\n");
10176 /* fix for glibc 2.1 */
10178 #define REG_EIP EIP
10179 #define REG_EBP EBP
10182 /* return the PC at frame level 'level'. Return non zero if not found */
10183 static int rt_get_caller_pc(unsigned long *paddr
,
10184 ucontext_t
*uc
, int level
)
10190 #if defined(__FreeBSD__)
10191 *paddr
= uc
->uc_mcontext
.mc_eip
;
10192 #elif defined(__dietlibc__)
10193 *paddr
= uc
->uc_mcontext
.eip
;
10195 *paddr
= uc
->uc_mcontext
.gregs
[REG_EIP
];
10199 #if defined(__FreeBSD__)
10200 fp
= uc
->uc_mcontext
.mc_ebp
;
10201 #elif defined(__dietlibc__)
10202 fp
= uc
->uc_mcontext
.ebp
;
10204 fp
= uc
->uc_mcontext
.gregs
[REG_EBP
];
10206 for(i
=1;i
<level
;i
++) {
10207 /* XXX: check address validity with program info */
10208 if (fp
<= 0x1000 || fp
>= 0xc0000000)
10210 fp
= ((unsigned long *)fp
)[0];
10212 *paddr
= ((unsigned long *)fp
)[1];
10216 #elif defined(__x86_64__)
10217 /* return the PC at frame level 'level'. Return non zero if not found */
10218 static int rt_get_caller_pc(unsigned long *paddr
,
10219 ucontext_t
*uc
, int level
)
10225 /* XXX: only support linux */
10226 *paddr
= uc
->uc_mcontext
.gregs
[REG_RIP
];
10229 fp
= uc
->uc_mcontext
.gregs
[REG_RBP
];
10230 for(i
=1;i
<level
;i
++) {
10231 /* XXX: check address validity with program info */
10234 fp
= ((unsigned long *)fp
)[0];
10236 *paddr
= ((unsigned long *)fp
)[1];
10241 #warning add arch specific rt_get_caller_pc()
10242 static int rt_get_caller_pc(unsigned long *paddr
,
10243 ucontext_t
*uc
, int level
)
10249 /* emit a run time error at position 'pc' */
10250 void rt_error(ucontext_t
*uc
, const char *fmt
, ...)
10257 fprintf(stderr
, "Runtime error: ");
10258 vfprintf(stderr
, fmt
, ap
);
10259 fprintf(stderr
, "\n");
10260 for(i
=0;i
<num_callers
;i
++) {
10261 if (rt_get_caller_pc(&pc
, uc
, i
) < 0)
10264 fprintf(stderr
, "at ");
10266 fprintf(stderr
, "by ");
10273 /* signal handler for fatal errors */
10274 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
10276 ucontext_t
*uc
= puc
;
10280 switch(siginf
->si_code
) {
10283 rt_error(uc
, "division by zero");
10286 rt_error(uc
, "floating point exception");
10292 if (rt_bound_error_msg
&& *rt_bound_error_msg
)
10293 rt_error(uc
, *rt_bound_error_msg
);
10295 rt_error(uc
, "dereferencing invalid pointer");
10298 rt_error(uc
, "illegal instruction");
10301 rt_error(uc
, "abort() called");
10304 rt_error(uc
, "caught signal %d", signum
);
10312 /* copy code into memory passed in by the caller and do all relocations
10313 (needed before using tcc_get_symbol()).
10314 returns -1 on error and required size if ptr is NULL */
10315 int tcc_relocate(TCCState
*s1
, void *ptr
)
10318 unsigned long offset
, length
, mem
;
10321 if (0 == s1
->runtime_added
) {
10322 s1
->runtime_added
= 1;
10324 #ifdef TCC_TARGET_PE
10325 pe_add_runtime(s1
);
10326 relocate_common_syms();
10327 tcc_add_linker_symbols(s1
);
10329 tcc_add_runtime(s1
);
10330 relocate_common_syms();
10331 tcc_add_linker_symbols(s1
);
10332 build_got_entries(s1
);
10336 offset
= 0, mem
= (unsigned long)ptr
;
10337 for(i
= 1; i
< s1
->nb_sections
; i
++) {
10338 s
= s1
->sections
[i
];
10339 if (0 == (s
->sh_flags
& SHF_ALLOC
))
10341 length
= s
->data_offset
;
10342 s
->sh_addr
= mem
? (mem
+ offset
+ 15) & ~15 : 0;
10343 offset
= (offset
+ length
+ 15) & ~15;
10346 /* relocate symbols */
10347 relocate_syms(s1
, 1);
10351 #ifdef TCC_TARGET_X86_64
10352 s1
->runtime_plt_and_got_offset
= 0;
10353 s1
->runtime_plt_and_got
= (char *)(mem
+ offset
);
10354 /* double the size of the buffer for got and plt entries
10355 XXX: calculate exact size for them? */
10360 return offset
+ 15;
10362 /* relocate each section */
10363 for(i
= 1; i
< s1
->nb_sections
; i
++) {
10364 s
= s1
->sections
[i
];
10366 relocate_section(s1
, s
);
10369 for(i
= 1; i
< s1
->nb_sections
; i
++) {
10370 s
= s1
->sections
[i
];
10371 if (0 == (s
->sh_flags
& SHF_ALLOC
))
10373 length
= s
->data_offset
;
10374 // printf("%-12s %08x %04x\n", s->name, s->sh_addr, length);
10375 ptr
= (void*)s
->sh_addr
;
10376 if (NULL
== s
->data
|| s
->sh_type
== SHT_NOBITS
)
10377 memset(ptr
, 0, length
);
10379 memcpy(ptr
, s
->data
, length
);
10380 /* mark executable sections as executable in memory */
10381 if (s
->sh_flags
& SHF_EXECINSTR
)
10382 set_pages_executable(ptr
, length
);
10384 #ifdef TCC_TARGET_X86_64
10385 set_pages_executable(s1
->runtime_plt_and_got
,
10386 s1
->runtime_plt_and_got_offset
);
10391 /* launch the compiled program with the given arguments */
10392 int tcc_run(TCCState
*s1
, int argc
, char **argv
)
10394 int (*prog_main
)(int, char **);
10398 ret
= tcc_relocate(s1
, NULL
);
10401 ptr
= tcc_malloc(ret
);
10402 tcc_relocate(s1
, ptr
);
10404 prog_main
= tcc_get_symbol_err(s1
, "main");
10407 #ifdef CONFIG_TCC_BACKTRACE
10408 struct sigaction sigact
;
10409 /* install TCC signal handlers to print debug info on fatal
10411 sigact
.sa_flags
= SA_SIGINFO
| SA_RESETHAND
;
10412 sigact
.sa_sigaction
= sig_error
;
10413 sigemptyset(&sigact
.sa_mask
);
10414 sigaction(SIGFPE
, &sigact
, NULL
);
10415 sigaction(SIGILL
, &sigact
, NULL
);
10416 sigaction(SIGSEGV
, &sigact
, NULL
);
10417 sigaction(SIGBUS
, &sigact
, NULL
);
10418 sigaction(SIGABRT
, &sigact
, NULL
);
10420 error("debug mode not available");
10424 #ifdef CONFIG_TCC_BCHECK
10425 if (do_bounds_check
) {
10426 void (*bound_init
)(void);
10428 /* set error function */
10429 rt_bound_error_msg
= tcc_get_symbol_err(s1
, "__bound_error_msg");
10431 /* XXX: use .init section so that it also work in binary ? */
10432 bound_init
= (void *)tcc_get_symbol_err(s1
, "__bound_init");
10436 ret
= (*prog_main
)(argc
, argv
);
10441 void tcc_memstats(void)
10444 printf("memory in use: %d\n", mem_cur_size
);
10448 static void tcc_cleanup(void)
10452 if (NULL
== tcc_state
)
10456 /* free -D defines */
10457 free_defines(NULL
);
10460 n
= tok_ident
- TOK_IDENT
;
10461 for(i
= 0; i
< n
; i
++)
10462 tcc_free(table_ident
[i
]);
10463 tcc_free(table_ident
);
10465 /* free sym_pools */
10466 dynarray_reset(&sym_pools
, &nb_sym_pools
);
10467 /* string buffer */
10468 cstr_free(&tokcstr
);
10469 /* reset symbol stack */
10470 sym_free_first
= NULL
;
10471 /* cleanup from error/setjmp */
10475 TCCState
*tcc_new(void)
10484 s
= tcc_mallocz(sizeof(TCCState
));
10488 s
->output_type
= TCC_OUTPUT_MEMORY
;
10490 /* init isid table */
10491 for(i
=CH_EOF
;i
<256;i
++)
10492 isidnum_table
[i
-CH_EOF
] = isid(i
) || isnum(i
);
10494 /* add all tokens */
10495 table_ident
= NULL
;
10496 memset(hash_ident
, 0, TOK_HASH_SIZE
* sizeof(TokenSym
*));
10498 tok_ident
= TOK_IDENT
;
10507 ts
= tok_alloc(p
, r
- p
- 1);
10511 /* we add dummy defines for some special macros to speed up tests
10512 and to have working defined() */
10513 define_push(TOK___LINE__
, MACRO_OBJ
, NULL
, NULL
);
10514 define_push(TOK___FILE__
, MACRO_OBJ
, NULL
, NULL
);
10515 define_push(TOK___DATE__
, MACRO_OBJ
, NULL
, NULL
);
10516 define_push(TOK___TIME__
, MACRO_OBJ
, NULL
, NULL
);
10518 /* standard defines */
10519 tcc_define_symbol(s
, "__STDC__", NULL
);
10520 tcc_define_symbol(s
, "__STDC_VERSION__", "199901L");
10521 #if defined(TCC_TARGET_I386)
10522 tcc_define_symbol(s
, "__i386__", NULL
);
10524 #if defined(TCC_TARGET_X86_64)
10525 tcc_define_symbol(s
, "__x86_64__", NULL
);
10527 #if defined(TCC_TARGET_ARM)
10528 tcc_define_symbol(s
, "__ARM_ARCH_4__", NULL
);
10529 tcc_define_symbol(s
, "__arm_elf__", NULL
);
10530 tcc_define_symbol(s
, "__arm_elf", NULL
);
10531 tcc_define_symbol(s
, "arm_elf", NULL
);
10532 tcc_define_symbol(s
, "__arm__", NULL
);
10533 tcc_define_symbol(s
, "__arm", NULL
);
10534 tcc_define_symbol(s
, "arm", NULL
);
10535 tcc_define_symbol(s
, "__APCS_32__", NULL
);
10537 #ifdef TCC_TARGET_PE
10538 tcc_define_symbol(s
, "_WIN32", NULL
);
10540 tcc_define_symbol(s
, "__unix__", NULL
);
10541 tcc_define_symbol(s
, "__unix", NULL
);
10542 #if defined(__linux)
10543 tcc_define_symbol(s
, "__linux__", NULL
);
10544 tcc_define_symbol(s
, "__linux", NULL
);
10547 /* tiny C specific defines */
10548 tcc_define_symbol(s
, "__TINYC__", NULL
);
10550 /* tiny C & gcc defines */
10551 tcc_define_symbol(s
, "__SIZE_TYPE__", "unsigned int");
10552 tcc_define_symbol(s
, "__PTRDIFF_TYPE__", "int");
10553 #ifdef TCC_TARGET_PE
10554 tcc_define_symbol(s
, "__WCHAR_TYPE__", "unsigned short");
10556 tcc_define_symbol(s
, "__WCHAR_TYPE__", "int");
10559 #ifndef TCC_TARGET_PE
10560 /* default library paths */
10561 tcc_add_library_path(s
, CONFIG_SYSROOT
"/usr/local/lib");
10562 tcc_add_library_path(s
, CONFIG_SYSROOT
"/usr/lib");
10563 tcc_add_library_path(s
, CONFIG_SYSROOT
"/lib");
10566 /* no section zero */
10567 dynarray_add((void ***)&s
->sections
, &s
->nb_sections
, NULL
);
10569 /* create standard sections */
10570 text_section
= new_section(s
, ".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
10571 data_section
= new_section(s
, ".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
10572 bss_section
= new_section(s
, ".bss", SHT_NOBITS
, SHF_ALLOC
| SHF_WRITE
);
10574 /* symbols are always generated for linking stage */
10575 symtab_section
= new_symtab(s
, ".symtab", SHT_SYMTAB
, 0,
10577 ".hashtab", SHF_PRIVATE
);
10578 strtab_section
= symtab_section
->link
;
10580 /* private symbol table for dynamic symbols */
10581 s
->dynsymtab_section
= new_symtab(s
, ".dynsymtab", SHT_SYMTAB
, SHF_PRIVATE
,
10583 ".dynhashtab", SHF_PRIVATE
);
10584 s
->alacarte_link
= 1;
10586 #ifdef CHAR_IS_UNSIGNED
10587 s
->char_is_unsigned
= 1;
10589 #if defined(TCC_TARGET_PE) && 0
10590 /* XXX: currently the PE linker is not ready to support that */
10591 s
->leading_underscore
= 1;
10596 void tcc_delete(TCCState
*s1
)
10602 /* free all sections */
10603 for(i
= 1; i
< s1
->nb_sections
; i
++)
10604 free_section(s1
->sections
[i
]);
10605 dynarray_reset(&s1
->sections
, &s1
->nb_sections
);
10607 for(i
= 0; i
< s1
->nb_priv_sections
; i
++)
10608 free_section(s1
->priv_sections
[i
]);
10609 dynarray_reset(&s1
->priv_sections
, &s1
->nb_priv_sections
);
10611 /* free any loaded DLLs */
10612 for ( i
= 0; i
< s1
->nb_loaded_dlls
; i
++) {
10613 DLLReference
*ref
= s1
->loaded_dlls
[i
];
10615 dlclose(ref
->handle
);
10618 /* free loaded dlls array */
10619 dynarray_reset(&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
);
10621 /* free library paths */
10622 dynarray_reset(&s1
->library_paths
, &s1
->nb_library_paths
);
10624 /* free include paths */
10625 dynarray_reset(&s1
->cached_includes
, &s1
->nb_cached_includes
);
10626 dynarray_reset(&s1
->include_paths
, &s1
->nb_include_paths
);
10627 dynarray_reset(&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
);
10632 int tcc_add_include_path(TCCState
*s1
, const char *pathname
)
10636 pathname1
= tcc_strdup(pathname
);
10637 dynarray_add((void ***)&s1
->include_paths
, &s1
->nb_include_paths
, pathname1
);
10641 int tcc_add_sysinclude_path(TCCState
*s1
, const char *pathname
)
10645 pathname1
= tcc_strdup(pathname
);
10646 dynarray_add((void ***)&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
, pathname1
);
10650 static int tcc_add_file_internal(TCCState
*s1
, const char *filename
, int flags
)
10655 BufferedFile
*saved_file
;
10657 /* find source file type with extension */
10658 ext
= tcc_fileextension(filename
);
10662 /* open the file */
10664 file
= tcc_open(s1
, filename
);
10666 if (flags
& AFF_PRINT_ERROR
) {
10667 error_noabort("file '%s' not found", filename
);
10673 if (flags
& AFF_PREPROCESS
) {
10674 ret
= tcc_preprocess(s1
);
10675 } else if (!ext
[0] || !PATHCMP(ext
, "c")) {
10676 /* C file assumed */
10677 ret
= tcc_compile(s1
);
10679 #ifdef CONFIG_TCC_ASM
10680 if (!strcmp(ext
, "S")) {
10681 /* preprocessed assembler */
10682 ret
= tcc_assemble(s1
, 1);
10683 } else if (!strcmp(ext
, "s")) {
10684 /* non preprocessed assembler */
10685 ret
= tcc_assemble(s1
, 0);
10688 #ifdef TCC_TARGET_PE
10689 if (!PATHCMP(ext
, "def")) {
10690 ret
= pe_load_def_file(s1
, file
->fd
);
10695 /* assume executable format: auto guess file type */
10696 ret
= read(fd
, &ehdr
, sizeof(ehdr
));
10697 lseek(fd
, 0, SEEK_SET
);
10699 error_noabort("could not read header");
10701 } else if (ret
!= sizeof(ehdr
)) {
10702 goto try_load_script
;
10705 if (ehdr
.e_ident
[0] == ELFMAG0
&&
10706 ehdr
.e_ident
[1] == ELFMAG1
&&
10707 ehdr
.e_ident
[2] == ELFMAG2
&&
10708 ehdr
.e_ident
[3] == ELFMAG3
) {
10709 file
->line_num
= 0; /* do not display line number if error */
10710 if (ehdr
.e_type
== ET_REL
) {
10711 ret
= tcc_load_object_file(s1
, fd
, 0);
10712 } else if (ehdr
.e_type
== ET_DYN
) {
10713 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
10714 #ifdef TCC_TARGET_PE
10718 h
= dlopen(filename
, RTLD_GLOBAL
| RTLD_LAZY
);
10725 ret
= tcc_load_dll(s1
, fd
, filename
,
10726 (flags
& AFF_REFERENCED_DLL
) != 0);
10729 error_noabort("unrecognized ELF file");
10732 } else if (memcmp((char *)&ehdr
, ARMAG
, 8) == 0) {
10733 file
->line_num
= 0; /* do not display line number if error */
10734 ret
= tcc_load_archive(s1
, fd
);
10736 #ifdef TCC_TARGET_COFF
10737 if (*(uint16_t *)(&ehdr
) == COFF_C67_MAGIC
) {
10738 ret
= tcc_load_coff(s1
, fd
);
10741 #ifdef TCC_TARGET_PE
10742 if (pe_test_res_file(&ehdr
, ret
)) {
10743 ret
= pe_load_res_file(s1
, fd
);
10747 /* as GNU ld, consider it is an ld script if not recognized */
10749 ret
= tcc_load_ldscript(s1
);
10751 error_noabort("unrecognized file type");
10766 int tcc_add_file(TCCState
*s
, const char *filename
)
10768 return tcc_add_file_internal(s
, filename
, AFF_PRINT_ERROR
);
10771 int tcc_add_library_path(TCCState
*s
, const char *pathname
)
10775 pathname1
= tcc_strdup(pathname
);
10776 dynarray_add((void ***)&s
->library_paths
, &s
->nb_library_paths
, pathname1
);
10780 /* find and load a dll. Return non zero if not found */
10781 /* XXX: add '-rpath' option support ? */
10782 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
)
10787 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
10788 snprintf(buf
, sizeof(buf
), "%s/%s",
10789 s
->library_paths
[i
], filename
);
10790 if (tcc_add_file_internal(s
, buf
, flags
) == 0)
10796 /* the library name is the same as the argument of the '-l' option */
10797 int tcc_add_library(TCCState
*s
, const char *libraryname
)
10802 /* first we look for the dynamic library if not static linking */
10803 if (!s
->static_link
) {
10804 #ifdef TCC_TARGET_PE
10805 snprintf(buf
, sizeof(buf
), "%s.def", libraryname
);
10807 snprintf(buf
, sizeof(buf
), "lib%s.so", libraryname
);
10809 if (tcc_add_dll(s
, buf
, 0) == 0)
10813 /* then we look for the static library */
10814 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
10815 snprintf(buf
, sizeof(buf
), "%s/lib%s.a",
10816 s
->library_paths
[i
], libraryname
);
10817 if (tcc_add_file_internal(s
, buf
, 0) == 0)
10823 int tcc_add_symbol(TCCState
*s
, const char *name
, void *val
)
10825 add_elf_sym(symtab_section
, (unsigned long)val
, 0,
10826 ELFW(ST_INFO
)(STB_GLOBAL
, STT_NOTYPE
), 0,
10831 int tcc_set_output_type(TCCState
*s
, int output_type
)
10835 s
->output_type
= output_type
;
10837 if (!s
->nostdinc
) {
10838 /* default include paths */
10839 /* XXX: reverse order needed if -isystem support */
10840 #ifndef TCC_TARGET_PE
10841 tcc_add_sysinclude_path(s
, CONFIG_SYSROOT
"/usr/local/include");
10842 tcc_add_sysinclude_path(s
, CONFIG_SYSROOT
"/usr/include");
10844 snprintf(buf
, sizeof(buf
), "%s/include", tcc_lib_path
);
10845 tcc_add_sysinclude_path(s
, buf
);
10846 #ifdef TCC_TARGET_PE
10847 snprintf(buf
, sizeof(buf
), "%s/include/winapi", tcc_lib_path
);
10848 tcc_add_sysinclude_path(s
, buf
);
10852 /* if bound checking, then add corresponding sections */
10853 #ifdef CONFIG_TCC_BCHECK
10854 if (do_bounds_check
) {
10855 /* define symbol */
10856 tcc_define_symbol(s
, "__BOUNDS_CHECKING_ON", NULL
);
10857 /* create bounds sections */
10858 bounds_section
= new_section(s
, ".bounds",
10859 SHT_PROGBITS
, SHF_ALLOC
);
10860 lbounds_section
= new_section(s
, ".lbounds",
10861 SHT_PROGBITS
, SHF_ALLOC
);
10865 if (s
->char_is_unsigned
) {
10866 tcc_define_symbol(s
, "__CHAR_UNSIGNED__", NULL
);
10869 /* add debug sections */
10872 stab_section
= new_section(s
, ".stab", SHT_PROGBITS
, 0);
10873 stab_section
->sh_entsize
= sizeof(Stab_Sym
);
10874 stabstr_section
= new_section(s
, ".stabstr", SHT_STRTAB
, 0);
10875 put_elf_str(stabstr_section
, "");
10876 stab_section
->link
= stabstr_section
;
10877 /* put first entry */
10878 put_stabs("", 0, 0, 0, 0);
10881 /* add libc crt1/crti objects */
10882 #ifndef TCC_TARGET_PE
10883 if ((output_type
== TCC_OUTPUT_EXE
|| output_type
== TCC_OUTPUT_DLL
) &&
10885 if (output_type
!= TCC_OUTPUT_DLL
)
10886 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crt1.o");
10887 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crti.o");
10891 #ifdef TCC_TARGET_PE
10892 snprintf(buf
, sizeof(buf
), "%s/lib", tcc_lib_path
);
10893 tcc_add_library_path(s
, buf
);
10899 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10900 #define FD_INVERT 0x0002 /* invert value before storing */
10902 typedef struct FlagDef
{
10908 static const FlagDef warning_defs
[] = {
10909 { offsetof(TCCState
, warn_unsupported
), 0, "unsupported" },
10910 { offsetof(TCCState
, warn_write_strings
), 0, "write-strings" },
10911 { offsetof(TCCState
, warn_error
), 0, "error" },
10912 { offsetof(TCCState
, warn_implicit_function_declaration
), WD_ALL
,
10913 "implicit-function-declaration" },
10916 static int set_flag(TCCState
*s
, const FlagDef
*flags
, int nb_flags
,
10917 const char *name
, int value
)
10924 if (r
[0] == 'n' && r
[1] == 'o' && r
[2] == '-') {
10928 for(i
= 0, p
= flags
; i
< nb_flags
; i
++, p
++) {
10929 if (!strcmp(r
, p
->name
))
10934 if (p
->flags
& FD_INVERT
)
10936 *(int *)((uint8_t *)s
+ p
->offset
) = value
;
10941 /* set/reset a warning */
10942 int tcc_set_warning(TCCState
*s
, const char *warning_name
, int value
)
10947 if (!strcmp(warning_name
, "all")) {
10948 for(i
= 0, p
= warning_defs
; i
< countof(warning_defs
); i
++, p
++) {
10949 if (p
->flags
& WD_ALL
)
10950 *(int *)((uint8_t *)s
+ p
->offset
) = 1;
10954 return set_flag(s
, warning_defs
, countof(warning_defs
),
10955 warning_name
, value
);
10959 static const FlagDef flag_defs
[] = {
10960 { offsetof(TCCState
, char_is_unsigned
), 0, "unsigned-char" },
10961 { offsetof(TCCState
, char_is_unsigned
), FD_INVERT
, "signed-char" },
10962 { offsetof(TCCState
, nocommon
), FD_INVERT
, "common" },
10963 { offsetof(TCCState
, leading_underscore
), 0, "leading-underscore" },
10966 /* set/reset a flag */
10967 int tcc_set_flag(TCCState
*s
, const char *flag_name
, int value
)
10969 return set_flag(s
, flag_defs
, countof(flag_defs
),
10973 /* set CONFIG_TCCDIR at runtime */
10974 void tcc_set_lib_path(TCCState
*s
, const char *path
)
10976 tcc_lib_path
= tcc_strdup(path
);
10979 #if !defined(LIBTCC)
10981 static int64_t getclock_us(void)
10986 return (tb
.time
* 1000LL + tb
.millitm
) * 1000LL;
10989 gettimeofday(&tv
, NULL
);
10990 return tv
.tv_sec
* 1000000LL + tv
.tv_usec
;
10996 printf("tcc version " TCC_VERSION
" - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10997 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10998 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-soname name]\n"
10999 " [-static] [infile1 infile2...] [-run infile args...]\n"
11001 "General options:\n"
11002 " -v display current version, increase verbosity\n"
11003 " -c compile only - generate an object file\n"
11004 " -o outfile set output filename\n"
11005 " -Bdir set tcc internal library path\n"
11006 " -bench output compilation statistics\n"
11007 " -run run compiled source\n"
11008 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
11009 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
11010 " -w disable all warnings\n"
11011 "Preprocessor options:\n"
11012 " -E preprocess only\n"
11013 " -Idir add include path 'dir'\n"
11014 " -Dsym[=val] define 'sym' with value 'val'\n"
11015 " -Usym undefine 'sym'\n"
11016 "Linker options:\n"
11017 " -Ldir add library path 'dir'\n"
11018 " -llib link with dynamic or static library 'lib'\n"
11019 " -shared generate a shared library\n"
11020 " -soname set name for shared library to be used at runtime\n"
11021 " -static static linking\n"
11022 " -rdynamic export all global symbols to dynamic linker\n"
11023 " -r generate (relocatable) object file\n"
11024 "Debugger options:\n"
11025 " -g generate runtime debug info\n"
11026 #ifdef CONFIG_TCC_BCHECK
11027 " -b compile with built-in memory and bounds checker (implies -g)\n"
11029 #ifdef CONFIG_TCC_BACKTRACE
11030 " -bt N show N callers in stack traces\n"
11035 #define TCC_OPTION_HAS_ARG 0x0001
11036 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
11038 typedef struct TCCOption
{
11067 TCC_OPTION_nostdinc
,
11068 TCC_OPTION_nostdlib
,
11069 TCC_OPTION_print_search_dirs
,
11070 TCC_OPTION_rdynamic
,
11078 static const TCCOption tcc_options
[] = {
11079 { "h", TCC_OPTION_HELP
, 0 },
11080 { "?", TCC_OPTION_HELP
, 0 },
11081 { "I", TCC_OPTION_I
, TCC_OPTION_HAS_ARG
},
11082 { "D", TCC_OPTION_D
, TCC_OPTION_HAS_ARG
},
11083 { "U", TCC_OPTION_U
, TCC_OPTION_HAS_ARG
},
11084 { "L", TCC_OPTION_L
, TCC_OPTION_HAS_ARG
},
11085 { "B", TCC_OPTION_B
, TCC_OPTION_HAS_ARG
},
11086 { "l", TCC_OPTION_l
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11087 { "bench", TCC_OPTION_bench
, 0 },
11088 { "bt", TCC_OPTION_bt
, TCC_OPTION_HAS_ARG
},
11089 #ifdef CONFIG_TCC_BCHECK
11090 { "b", TCC_OPTION_b
, 0 },
11092 { "g", TCC_OPTION_g
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11093 { "c", TCC_OPTION_c
, 0 },
11094 { "static", TCC_OPTION_static
, 0 },
11095 { "shared", TCC_OPTION_shared
, 0 },
11096 { "soname", TCC_OPTION_soname
, TCC_OPTION_HAS_ARG
},
11097 { "o", TCC_OPTION_o
, TCC_OPTION_HAS_ARG
},
11098 { "run", TCC_OPTION_run
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11099 { "rdynamic", TCC_OPTION_rdynamic
, 0 },
11100 { "r", TCC_OPTION_r
, 0 },
11101 { "Wl,", TCC_OPTION_Wl
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11102 { "W", TCC_OPTION_W
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11103 { "O", TCC_OPTION_O
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11104 { "m", TCC_OPTION_m
, TCC_OPTION_HAS_ARG
},
11105 { "f", TCC_OPTION_f
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11106 { "nostdinc", TCC_OPTION_nostdinc
, 0 },
11107 { "nostdlib", TCC_OPTION_nostdlib
, 0 },
11108 { "print-search-dirs", TCC_OPTION_print_search_dirs
, 0 },
11109 { "v", TCC_OPTION_v
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
11110 { "w", TCC_OPTION_w
, 0 },
11111 { "pipe", TCC_OPTION_pipe
, 0},
11112 { "E", TCC_OPTION_E
, 0},
11116 /* convert 'str' into an array of space separated strings */
11117 static int expand_args(char ***pargv
, const char *str
)
11126 while (is_space(*str
))
11131 while (*str
!= '\0' && !is_space(*str
))
11134 arg
= tcc_malloc(len
+ 1);
11135 memcpy(arg
, s1
, len
);
11137 dynarray_add((void ***)&argv
, &argc
, arg
);
11143 static char **files
;
11144 static int nb_files
, nb_libraries
;
11145 static int multiple_files
;
11146 static int print_search_dirs
;
11147 static int output_type
;
11148 static int reloc_output
;
11149 static const char *outfile
;
11151 int parse_args(TCCState
*s
, int argc
, char **argv
)
11154 const TCCOption
*popt
;
11155 const char *optarg
, *p1
, *r1
;
11159 while (optind
< argc
) {
11161 r
= argv
[optind
++];
11162 if (r
[0] != '-' || r
[1] == '\0') {
11163 /* add a new file */
11164 dynarray_add((void ***)&files
, &nb_files
, r
);
11165 if (!multiple_files
) {
11167 /* argv[0] will be this file */
11171 /* find option in table (match only the first chars */
11172 popt
= tcc_options
;
11176 error("invalid option -- '%s'", r
);
11189 if (popt
->flags
& TCC_OPTION_HAS_ARG
) {
11190 if (*r1
!= '\0' || (popt
->flags
& TCC_OPTION_NOSEP
)) {
11193 if (optind
>= argc
)
11194 error("argument to '%s' is missing", r
);
11195 optarg
= argv
[optind
++];
11203 switch(popt
->index
) {
11204 case TCC_OPTION_HELP
:
11208 if (tcc_add_include_path(s
, optarg
) < 0)
11209 error("too many include paths");
11214 sym
= (char *)optarg
;
11215 value
= strchr(sym
, '=');
11220 tcc_define_symbol(s
, sym
, value
);
11224 tcc_undefine_symbol(s
, optarg
);
11227 tcc_add_library_path(s
, optarg
);
11230 /* set tcc utilities path (mainly for tcc development) */
11231 tcc_set_lib_path(s
, optarg
);
11234 dynarray_add((void ***)&files
, &nb_files
, r
);
11237 case TCC_OPTION_bench
:
11240 #ifdef CONFIG_TCC_BACKTRACE
11241 case TCC_OPTION_bt
:
11242 num_callers
= atoi(optarg
);
11245 #ifdef CONFIG_TCC_BCHECK
11247 do_bounds_check
= 1;
11255 multiple_files
= 1;
11256 output_type
= TCC_OUTPUT_OBJ
;
11258 case TCC_OPTION_static
:
11259 s
->static_link
= 1;
11261 case TCC_OPTION_shared
:
11262 output_type
= TCC_OUTPUT_DLL
;
11264 case TCC_OPTION_soname
:
11265 s
->soname
= optarg
;
11268 multiple_files
= 1;
11272 /* generate a .o merging several output files */
11274 output_type
= TCC_OUTPUT_OBJ
;
11276 case TCC_OPTION_nostdinc
:
11279 case TCC_OPTION_nostdlib
:
11282 case TCC_OPTION_print_search_dirs
:
11283 print_search_dirs
= 1;
11285 case TCC_OPTION_run
:
11289 argc1
= expand_args(&argv1
, optarg
);
11291 parse_args(s
, argc1
, argv1
);
11293 multiple_files
= 0;
11294 output_type
= TCC_OUTPUT_MEMORY
;
11299 if (0 == verbose
++)
11300 printf("tcc version %s\n", TCC_VERSION
);
11301 } while (*optarg
++ == 'v');
11304 if (tcc_set_flag(s
, optarg
, 1) < 0 && s
->warn_unsupported
)
11305 goto unsupported_option
;
11308 if (tcc_set_warning(s
, optarg
, 1) < 0 &&
11309 s
->warn_unsupported
)
11310 goto unsupported_option
;
11315 case TCC_OPTION_rdynamic
:
11318 case TCC_OPTION_Wl
:
11321 if (strstart(optarg
, "-Ttext,", &p
)) {
11322 s
->text_addr
= strtoul(p
, NULL
, 16);
11323 s
->has_text_addr
= 1;
11324 } else if (strstart(optarg
, "--oformat,", &p
)) {
11325 if (strstart(p
, "elf32-", NULL
)) {
11326 s
->output_format
= TCC_OUTPUT_FORMAT_ELF
;
11327 } else if (!strcmp(p
, "binary")) {
11328 s
->output_format
= TCC_OUTPUT_FORMAT_BINARY
;
11330 #ifdef TCC_TARGET_COFF
11331 if (!strcmp(p
, "coff")) {
11332 s
->output_format
= TCC_OUTPUT_FORMAT_COFF
;
11336 error("target %s not found", p
);
11339 error("unsupported linker option '%s'", optarg
);
11344 output_type
= TCC_OUTPUT_PREPROCESS
;
11347 if (s
->warn_unsupported
) {
11348 unsupported_option
:
11349 warning("unsupported option '%s'", r
);
11358 int main(int argc
, char **argv
)
11362 int nb_objfiles
, ret
, optind
;
11363 char objfilename
[1024];
11364 int64_t start_time
= 0;
11368 tcc_set_lib_path_w32(s
);
11370 output_type
= TCC_OUTPUT_EXE
;
11372 multiple_files
= 1;
11377 print_search_dirs
= 0;
11380 optind
= parse_args(s
, argc
- 1, argv
+ 1);
11381 if (print_search_dirs
) {
11382 /* enough for Linux kernel */
11383 printf("install: %s/\n", tcc_lib_path
);
11386 if (optind
== 0 || nb_files
== 0) {
11387 if (optind
&& verbose
)
11393 nb_objfiles
= nb_files
- nb_libraries
;
11395 /* if outfile provided without other options, we output an
11397 if (outfile
&& output_type
== TCC_OUTPUT_MEMORY
)
11398 output_type
= TCC_OUTPUT_EXE
;
11400 /* check -c consistency : only single file handled. XXX: checks file type */
11401 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
11402 /* accepts only a single input file */
11403 if (nb_objfiles
!= 1)
11404 error("cannot specify multiple files with -c");
11405 if (nb_libraries
!= 0)
11406 error("cannot specify libraries with -c");
11410 if (output_type
== TCC_OUTPUT_PREPROCESS
) {
11412 s
->outfile
= stdout
;
11414 s
->outfile
= fopen(outfile
, "w");
11416 error("could not open '%s", outfile
);
11418 } else if (output_type
!= TCC_OUTPUT_MEMORY
) {
11420 /* compute default outfile name */
11423 strcmp(files
[0], "-") == 0 ? "a" : tcc_basename(files
[0]);
11424 pstrcpy(objfilename
, sizeof(objfilename
), name
);
11425 ext
= tcc_fileextension(objfilename
);
11426 #ifdef TCC_TARGET_PE
11427 if (output_type
== TCC_OUTPUT_DLL
)
11428 strcpy(ext
, ".dll");
11430 if (output_type
== TCC_OUTPUT_EXE
)
11431 strcpy(ext
, ".exe");
11434 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
&& *ext
)
11437 pstrcpy(objfilename
, sizeof(objfilename
), "a.out");
11438 outfile
= objfilename
;
11443 start_time
= getclock_us();
11446 tcc_set_output_type(s
, output_type
);
11448 /* compile or add each files or library */
11449 for(i
= 0; i
< nb_files
&& ret
== 0; i
++) {
11450 const char *filename
;
11452 filename
= files
[i
];
11453 if (output_type
== TCC_OUTPUT_PREPROCESS
) {
11454 if (tcc_add_file_internal(s
, filename
,
11455 AFF_PRINT_ERROR
| AFF_PREPROCESS
) < 0)
11457 } else if (filename
[0] == '-' && filename
[1]) {
11458 if (tcc_add_library(s
, filename
+ 2) < 0)
11459 error("cannot find %s", filename
);
11462 printf("-> %s\n", filename
);
11463 if (tcc_add_file(s
, filename
) < 0)
11468 /* free all files */
11476 total_time
= (double)(getclock_us() - start_time
) / 1000000.0;
11477 if (total_time
< 0.001)
11478 total_time
= 0.001;
11479 if (total_bytes
< 1)
11481 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
11482 tok_ident
- TOK_IDENT
, total_lines
, total_bytes
,
11483 total_time
, (int)(total_lines
/ total_time
),
11484 total_bytes
/ total_time
/ 1000000.0);
11487 if (s
->output_type
== TCC_OUTPUT_PREPROCESS
) {
11489 fclose(s
->outfile
);
11490 } else if (s
->output_type
== TCC_OUTPUT_MEMORY
) {
11491 ret
= tcc_run(s
, argc
- optind
, argv
+ optind
);
11493 ret
= tcc_output_file(s
, outfile
) ? 1 : 0;
11495 /* XXX: cannot do it with bound checking because of the malloc hooks */
11496 if (!do_bounds_check
)
11501 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size
, mem_max_size
);