2 * TCC - Tiny C Compiler
4 * Copyright (c) 2001, 2002, 2003 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
36 #include <sys/timeb.h>
40 #include <sys/ucontext.h>
44 #ifndef CONFIG_TCC_STATIC
52 /* preprocessor debug */
54 /* include file debug */
62 /* target selection */
63 //#define TCC_TARGET_I386 /* i386 code generator */
64 //#define TCC_TARGET_ARM /* ARMv4 code generator */
66 /* default target is I386 */
67 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM)
68 #define TCC_TARGET_I386
71 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM)
72 #define CONFIG_TCC_BCHECK /* enable bound checking code */
75 /* define it to include assembler support */
76 #if !defined(TCC_TARGET_ARM)
77 #define CONFIG_TCC_ASM
80 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
81 executables or dlls */
82 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
84 #define INCLUDE_STACK_SIZE 32
85 #define IFDEF_STACK_SIZE 64
86 #define VSTACK_SIZE 64
87 #define STRING_MAX_SIZE 1024
89 #define TOK_HASH_SIZE 2048 /* must be a power of two */
90 #define TOK_ALLOC_INCR 512 /* must be a power of two */
91 #define TOK_STR_ALLOC_INCR_BITS 6
92 #define TOK_STR_ALLOC_INCR (1 << TOK_STR_ALLOC_INCR_BITS)
93 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
95 /* token symbol management */
96 typedef struct TokenSym
{
97 struct TokenSym
*hash_next
;
98 struct Sym
*sym_define
; /* direct pointer to define */
99 struct Sym
*sym_label
; /* direct pointer to label */
100 struct Sym
*sym_struct
; /* direct pointer to structure */
101 struct Sym
*sym_identifier
; /* direct pointer to identifier */
102 int tok
; /* token number */
107 typedef struct CString
{
108 int size
; /* size in bytes */
109 void *data
; /* either 'char *' or 'int *' */
111 void *data_allocated
; /* if non NULL, data has been malloced */
114 /* type definition */
115 typedef struct CType
{
121 typedef union CValue
{
127 unsigned int ul
; /* address (should be unsigned long on 64 bit cpu) */
129 unsigned long long ull
;
130 struct CString
*cstr
;
136 typedef struct SValue
{
137 CType type
; /* type */
138 unsigned short r
; /* register + flags */
139 unsigned short r2
; /* second register, used for 'long long'
140 type. If not used, set to VT_CONST */
141 CValue c
; /* constant, if VT_CONST */
142 struct Sym
*sym
; /* symbol, if (VT_SYM | VT_CONST) */
145 /* symbol management */
147 int v
; /* symbol token */
148 int r
; /* associated register */
149 int c
; /* associated number */
150 CType type
; /* associated type */
151 struct Sym
*next
; /* next related symbol */
152 struct Sym
*prev
; /* prev symbol in stack */
153 struct Sym
*prev_tok
; /* previous symbol for this token */
156 /* section definition */
157 /* XXX: use directly ELF structure for parameters ? */
158 /* special flag to indicate that the section should not be linked to
160 #define SHF_PRIVATE 0x80000000
162 typedef struct Section
{
163 unsigned long data_offset
; /* current data offset */
164 unsigned char *data
; /* section data */
165 unsigned long data_allocated
; /* used for realloc() handling */
166 int sh_name
; /* elf section name (only used during output) */
167 int sh_num
; /* elf section number */
168 int sh_type
; /* elf section type */
169 int sh_flags
; /* elf section flags */
170 int sh_info
; /* elf section info */
171 int sh_addralign
; /* elf section alignment */
172 int sh_entsize
; /* elf entry size */
173 unsigned long sh_size
; /* section size (only used during output) */
174 unsigned long sh_addr
; /* address at which the section is relocated */
175 unsigned long sh_offset
; /* address at which the section is relocated */
176 int nb_hashed_syms
; /* used to resize the hash table */
177 struct Section
*link
; /* link to another section */
178 struct Section
*reloc
; /* corresponding section for relocation, if any */
179 struct Section
*hash
; /* hash table for symbols */
180 struct Section
*next
;
181 char name
[1]; /* section name */
184 typedef struct DLLReference
{
189 /* GNUC attribute definition */
190 typedef struct AttributeDef
{
193 unsigned char func_call
; /* FUNC_CDECL or FUNC_STDCALL */
196 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
197 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
198 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
200 /* stored in 'Sym.c' field */
201 #define FUNC_NEW 1 /* ansi function prototype */
202 #define FUNC_OLD 2 /* old function prototype */
203 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
205 /* stored in 'Sym.r' field */
206 #define FUNC_CDECL 0 /* standard c call */
207 #define FUNC_STDCALL 1 /* pascal c call */
209 /* field 'Sym.t' for macros */
210 #define MACRO_OBJ 0 /* object like macro */
211 #define MACRO_FUNC 1 /* function like macro */
213 /* field 'Sym.r' for C labels */
214 #define LABEL_DEFINED 0 /* label is defined */
215 #define LABEL_FORWARD 1 /* label is forward defined */
216 #define LABEL_DECLARED 2 /* label is declared but never used */
218 /* type_decl() types */
219 #define TYPE_ABSTRACT 1 /* type without variable */
220 #define TYPE_DIRECT 2 /* type with variable */
222 #define IO_BUF_SIZE 8192
224 typedef struct BufferedFile
{
228 int line_num
; /* current line number - here to simplify code */
229 int ifndef_macro
; /* #ifndef macro / #endif search */
230 int ifndef_macro_saved
; /* saved ifndef_macro */
231 int *ifdef_stack_ptr
; /* ifdef_stack value at the start of the file */
232 char inc_type
; /* type of include */
233 char inc_filename
[512]; /* filename specified by the user */
234 char filename
[1024]; /* current filename - here to simplify code */
235 unsigned char buffer
[IO_BUF_SIZE
+ 1]; /* extra size for CH_EOB char */
238 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
239 #define CH_EOF (-1) /* end of file */
241 /* parsing state (used to save parser state to reparse part of the
242 source several times) */
243 typedef struct ParseState
{
250 /* used to record tokens */
251 typedef struct TokenString
{
258 /* include file cache, used to find files faster and also to eliminate
259 inclusion if the include file is protected by #ifndef ... #endif */
260 typedef struct CachedInclude
{
262 char type
; /* '"' or '>' to give include type */
263 char filename
[1]; /* path specified in #include */
267 static struct BufferedFile
*file
;
270 static CString tokcstr
; /* current parsed string, if any */
271 /* additional informations about token */
272 static int tok_flags
;
273 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
274 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
275 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
277 static int *macro_ptr
, *macro_ptr_allocated
;
278 static int *unget_saved_macro_ptr
;
279 static int unget_saved_buffer
[TOK_MAX_SIZE
+ 1];
280 static int unget_buffer_enabled
;
281 static int parse_flags
;
282 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
283 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
284 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
285 token. line feed is also
288 static Section
*text_section
, *data_section
, *bss_section
; /* predefined sections */
289 static Section
*cur_text_section
; /* current section where function code is
291 /* bound check related sections */
292 static Section
*bounds_section
; /* contains global data bound description */
293 static Section
*lbounds_section
; /* contains local data bound description */
294 /* symbol sections */
295 static Section
*symtab_section
, *strtab_section
;
298 static Section
*stab_section
, *stabstr_section
;
300 /* loc : local variable index
301 ind : output code index
303 anon_sym: anonymous symbol index
305 static int rsym
, anon_sym
, ind
, loc
;
306 /* expression generation modifiers */
307 static int const_wanted
; /* true if constant wanted */
308 static int nocode_wanted
; /* true if no code generation wanted for an expression */
309 static int global_expr
; /* true if compound literals must be allocated
310 globally (used during initializers parsing */
311 static CType func_vt
; /* current function return type (used by return
314 static int last_line_num
, last_ind
, func_ind
; /* debug last line number and pc */
315 static int tok_ident
;
316 static TokenSym
**table_ident
;
317 static TokenSym
*hash_ident
[TOK_HASH_SIZE
];
318 static char token_buf
[STRING_MAX_SIZE
+ 1];
319 static char *funcname
;
320 static Sym
*global_stack
, *local_stack
;
321 static Sym
*define_stack
;
322 static Sym
*global_label_stack
, *local_label_stack
;
324 static SValue vstack
[VSTACK_SIZE
], *vtop
;
325 /* some predefined types */
326 static CType char_pointer_type
, func_old_type
, int_type
;
327 /* true if isid(c) || isnum(c) */
328 static unsigned char isidnum_table
[256];
330 /* compile with debug symbol (and use them if error during execution) */
331 static int do_debug
= 0;
333 /* compile with built-in memory and bounds checker */
334 static int do_bounds_check
= 0;
336 /* display benchmark infos */
338 static int do_bench
= 0;
340 static int total_lines
;
341 static int total_bytes
;
343 /* use GNU C extensions */
344 static int gnu_ext
= 1;
346 /* use Tiny C extensions */
347 static int tcc_ext
= 1;
349 /* max number of callers shown if error */
350 static int num_callers
= 6;
351 static const char **rt_bound_error_msg
;
353 /* XXX: get rid of this ASAP */
354 static struct TCCState
*tcc_state
;
356 /* give the path of the tcc libraries */
357 static const char *tcc_lib_path
= CONFIG_TCC_LIBDIR
"/tcc";
362 BufferedFile
**include_stack_ptr
;
363 int *ifdef_stack_ptr
;
365 /* include file handling */
366 char **include_paths
;
367 int nb_include_paths
;
368 char **sysinclude_paths
;
369 int nb_sysinclude_paths
;
370 CachedInclude
**cached_includes
;
371 int nb_cached_includes
;
373 char **library_paths
;
374 int nb_library_paths
;
376 /* array of all loaded dlls (including those referenced by loaded
378 DLLReference
**loaded_dlls
;
383 int nb_sections
; /* number of sections, including first dummy section */
388 unsigned long *got_offsets
;
390 /* give the correspondance from symtab indexes to dynsym indexes */
391 int *symtab_to_dynsym
;
393 /* temporary dynamic symbol sections (for dll loading) */
394 Section
*dynsymtab_section
;
395 /* exported dynamic symbol section */
398 int nostdinc
; /* if true, no standard headers are added */
399 int nostdlib
; /* if true, no standard libraries are added */
401 /* if true, static linking is performed */
404 /* if true, all symbols are exported */
407 /* if true, only link in referenced objects from archive */
410 /* warning switches */
411 int warn_write_strings
;
412 int warn_unsupported
;
418 void (*error_func
)(void *opaque
, const char *msg
);
419 int error_set_jmp_enabled
;
420 jmp_buf error_jmp_buf
;
423 /* tiny assembler state */
426 /* see include_stack_ptr */
427 BufferedFile
*include_stack
[INCLUDE_STACK_SIZE
];
429 /* see ifdef_stack_ptr */
430 int ifdef_stack
[IFDEF_STACK_SIZE
];
433 /* The current value can be: */
434 #define VT_VALMASK 0x00ff
435 #define VT_CONST 0x00f0 /* constant in vc
436 (must be first non register value) */
437 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
438 #define VT_LOCAL 0x00f2 /* offset on stack */
439 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
440 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
441 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
442 #define VT_LVAL 0x0100 /* var is an lvalue */
443 #define VT_SYM 0x0200 /* a symbol value is added */
444 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
445 char/short stored in integer registers) */
446 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
447 dereferencing value */
448 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
449 bounding function call point is in vc */
450 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
451 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
452 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
453 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
456 #define VT_INT 0 /* integer type */
457 #define VT_BYTE 1 /* signed byte type */
458 #define VT_SHORT 2 /* short type */
459 #define VT_VOID 3 /* void type */
460 #define VT_PTR 4 /* pointer */
461 #define VT_ENUM 5 /* enum definition */
462 #define VT_FUNC 6 /* function type */
463 #define VT_STRUCT 7 /* struct/union definition */
464 #define VT_FLOAT 8 /* IEEE float */
465 #define VT_DOUBLE 9 /* IEEE double */
466 #define VT_LDOUBLE 10 /* IEEE long double */
467 #define VT_BOOL 11 /* ISOC99 boolean type */
468 #define VT_LLONG 12 /* 64 bit integer */
469 #define VT_LONG 13 /* long integer (NEVER USED as type, only
471 #define VT_BTYPE 0x000f /* mask for basic type */
472 #define VT_UNSIGNED 0x0010 /* unsigned type */
473 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
474 #define VT_BITFIELD 0x0040 /* bitfield modifier */
475 #define VT_CONSTANT 0x0800 /* const modifier */
476 #define VT_VOLATILE 0x1000 /* volatile modifier */
477 #define VT_SIGNED 0x2000 /* signed type */
480 #define VT_EXTERN 0x00000080 /* extern definition */
481 #define VT_STATIC 0x00000100 /* static variable */
482 #define VT_TYPEDEF 0x00000200 /* typedef definition */
483 #define VT_INLINE 0x00000400 /* inline definition */
485 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
487 /* type mask (except storage) */
488 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
489 #define VT_TYPE (~(VT_STORAGE))
493 /* warning: the following compare tokens depend on i386 asm code */
505 #define TOK_LAND 0xa0
509 #define TOK_MID 0xa3 /* inc/dec, to void constant */
511 #define TOK_UDIV 0xb0 /* unsigned division */
512 #define TOK_UMOD 0xb1 /* unsigned modulo */
513 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
514 #define TOK_CINT 0xb3 /* number in tokc */
515 #define TOK_CCHAR 0xb4 /* char constant in tokc */
516 #define TOK_STR 0xb5 /* pointer to string in tokc */
517 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
518 #define TOK_LCHAR 0xb7
519 #define TOK_LSTR 0xb8
520 #define TOK_CFLOAT 0xb9 /* float constant */
521 #define TOK_LINENUM 0xba /* line number info */
522 #define TOK_CDOUBLE 0xc0 /* double constant */
523 #define TOK_CLDOUBLE 0xc1 /* long double constant */
524 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
525 #define TOK_ADDC1 0xc3 /* add with carry generation */
526 #define TOK_ADDC2 0xc4 /* add with carry use */
527 #define TOK_SUBC1 0xc5 /* add with carry generation */
528 #define TOK_SUBC2 0xc6 /* add with carry use */
529 #define TOK_CUINT 0xc8 /* unsigned int constant */
530 #define TOK_CLLONG 0xc9 /* long long constant */
531 #define TOK_CULLONG 0xca /* unsigned long long constant */
532 #define TOK_ARROW 0xcb
533 #define TOK_DOTS 0xcc /* three dots */
534 #define TOK_SHR 0xcd /* unsigned shift right */
535 #define TOK_PPNUM 0xce /* preprocessor number */
537 #define TOK_SHL 0x01 /* shift left */
538 #define TOK_SAR 0x02 /* signed shift right */
540 /* assignement operators : normal operator or 0x80 */
541 #define TOK_A_MOD 0xa5
542 #define TOK_A_AND 0xa6
543 #define TOK_A_MUL 0xaa
544 #define TOK_A_ADD 0xab
545 #define TOK_A_SUB 0xad
546 #define TOK_A_DIV 0xaf
547 #define TOK_A_XOR 0xde
548 #define TOK_A_OR 0xfc
549 #define TOK_A_SHL 0x81
550 #define TOK_A_SAR 0x82
553 #define offsetof(type, field) ((size_t) &((type *)0)->field)
557 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
560 /* WARNING: the content of this string encodes token numbers */
561 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";
563 #define TOK_EOF (-1) /* end of file */
564 #define TOK_LINEFEED 10 /* line feed */
566 /* all identificators and strings have token above that */
567 #define TOK_IDENT 256
569 /* only used for i386 asm opcodes definitions */
570 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
573 DEF(TOK_ASM_ ## x ## b, #x "b") \
574 DEF(TOK_ASM_ ## x ## w, #x "w") \
575 DEF(TOK_ASM_ ## x ## l, #x "l") \
576 DEF(TOK_ASM_ ## x, #x)
579 DEF(TOK_ASM_ ## x ## w, #x "w") \
580 DEF(TOK_ASM_ ## x ## l, #x "l") \
581 DEF(TOK_ASM_ ## x, #x)
584 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
585 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
586 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
587 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
590 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
591 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
594 #define DEF_ASMTEST(x) \
626 #define TOK_ASM_int TOK_INT
629 TOK_LAST
= TOK_IDENT
- 1,
630 #define DEF(id, str) id,
635 static const char tcc_keywords
[] =
636 #define DEF(id, str) str "\0"
641 #define TOK_UIDENT TOK_DEFINE
644 #define snprintf _snprintf
645 #define vsnprintf _vsnprintf
648 #if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__)
649 /* currently incorrect */
650 long double strtold(const char *nptr
, char **endptr
)
652 return (long double)strtod(nptr
, endptr
);
654 float strtof(const char *nptr
, char **endptr
)
656 return (float)strtod(nptr
, endptr
);
659 /* XXX: need to define this to use them in non ISOC99 context */
660 extern float strtof (const char *__nptr
, char **__endptr
);
661 extern long double strtold (const char *__nptr
, char **__endptr
);
664 static char *pstrcpy(char *buf
, int buf_size
, const char *s
);
665 static char *pstrcat(char *buf
, int buf_size
, const char *s
);
667 static void next(void);
668 static void next_nomacro(void);
669 static void parse_expr_type(CType
*type
);
670 static void expr_type(CType
*type
);
671 static void unary_type(CType
*type
);
672 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
673 int case_reg
, int is_expr
);
674 static int expr_const(void);
675 static void expr_eq(void);
676 static void gexpr(void);
677 static void decl(int l
);
678 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
679 int first
, int size_only
);
680 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
681 int has_init
, int v
, int scope
);
683 void gv2(int rc1
, int rc2
);
684 void move_reg(int r
, int s
);
685 void save_regs(int n
);
686 void save_reg(int r
);
691 int get_reg_ex(int rc
,int rc2
);
693 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
694 const int *macro_str
, int can_read_stream
);
695 int save_reg_forced(int r
);
697 void force_charshort_cast(int t
);
698 static void gen_cast(CType
*type
);
700 static Sym
*sym_find(int v
);
701 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
);
704 static int type_size(CType
*type
, int *a
);
705 static inline CType
*pointed_type(CType
*type
);
706 static int pointed_size(CType
*type
);
707 static int lvalue_type(int t
);
708 static int parse_btype(CType
*type
, AttributeDef
*ad
);
709 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
);
710 static int is_compatible_types(CType
*type1
, CType
*type2
);
712 int ieee_finite(double d
);
713 void error(const char *fmt
, ...);
716 static void vpush_global_sym(CType
*type
, int v
);
717 void vset(CType
*type
, int r
, int v
);
718 void type_to_str(char *buf
, int buf_size
,
719 CType
*type
, const char *varstr
);
720 char *get_tok_str(int v
, CValue
*cv
);
721 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
722 unsigned long offset
, unsigned long size
);
723 static Sym
*external_global_sym(int v
, CType
*type
, int r
);
725 /* section generation */
726 static void section_realloc(Section
*sec
, unsigned long new_size
);
727 static void *section_ptr_add(Section
*sec
, unsigned long size
);
728 static void put_extern_sym(Sym
*sym
, Section
*section
,
729 unsigned long value
, unsigned long size
);
730 static void greloc(Section
*s
, Sym
*sym
, unsigned long addr
, int type
);
731 static int put_elf_str(Section
*s
, const char *sym
);
732 static int put_elf_sym(Section
*s
,
733 unsigned long value
, unsigned long size
,
734 int info
, int other
, int shndx
, const char *name
);
735 static int add_elf_sym(Section
*s
, unsigned long value
, unsigned long size
,
736 int info
, int sh_num
, const char *name
);
737 static void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
738 int type
, int symbol
);
739 static void put_stabs(const char *str
, int type
, int other
, int desc
,
740 unsigned long value
);
741 static void put_stabs_r(const char *str
, int type
, int other
, int desc
,
742 unsigned long value
, Section
*sec
, int sym_index
);
743 static void put_stabn(int type
, int other
, int desc
, int value
);
744 static void put_stabd(int type
, int other
, int desc
);
745 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
);
747 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
748 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
749 static int tcc_add_file_internal(TCCState
*s
, const char *filename
, int flags
);
753 #ifdef CONFIG_TCC_ASM
755 typedef struct ExprValue
{
760 #define MAX_ASM_OPERANDS 30
762 typedef struct ASMOperand
{
763 int id
; /* GCC 3 optionnal identifier (0 if number only supported */
765 char asm_str
[16]; /* computed asm string for operand */
766 SValue
*vt
; /* C value of the expression */
767 int ref_index
; /* if >= 0, gives reference to a output constraint */
768 int priority
; /* priority, used to assign registers */
769 int reg
; /* if >= 0, register number used for this operand */
770 int is_llong
; /* true if double register value */
773 static void asm_expr(TCCState
*s1
, ExprValue
*pe
);
774 static int asm_int_expr(TCCState
*s1
);
775 static int find_constraint(ASMOperand
*operands
, int nb_operands
,
776 const char *name
, const char **pp
);
778 static int tcc_assemble(TCCState
*s1
, int do_preprocess
);
782 static void asm_instr(void);
784 /* true if float/double/long double type */
785 static inline int is_float(int t
)
789 return bt
== VT_LDOUBLE
|| bt
== VT_DOUBLE
|| bt
== VT_FLOAT
;
792 #ifdef TCC_TARGET_I386
793 #include "i386-gen.c"
796 #ifdef TCC_TARGET_ARM
800 #ifdef CONFIG_TCC_STATIC
802 #define RTLD_LAZY 0x001
803 #define RTLD_NOW 0x002
804 #define RTLD_GLOBAL 0x100
805 #define RTLD_DEFAULT NULL
807 /* dummy function for profiling */
808 void *dlopen(const char *filename
, int flag
)
813 const char *dlerror(void)
818 typedef struct TCCSyms
{
823 #define TCCSYM(a) { #a, &a, },
825 /* add the symbol you want here if no dynamic linking is done */
826 static TCCSyms tcc_syms
[] = {
834 void *dlsym(void *handle
, const char *symbol
)
838 while (p
->str
!= NULL
) {
839 if (!strcmp(p
->str
, symbol
))
848 /********************************************************/
850 /* we use our own 'finite' function to avoid potential problems with
851 non standard math libs */
852 /* XXX: endianness dependent */
853 int ieee_finite(double d
)
856 return ((unsigned)((p
[1] | 0x800fffff) + 1)) >> 31;
859 /* copy a string and truncate it. */
860 static char *pstrcpy(char *buf
, int buf_size
, const char *s
)
867 q_end
= buf
+ buf_size
- 1;
879 /* strcat and truncate. */
880 static char *pstrcat(char *buf
, int buf_size
, const char *s
)
885 pstrcpy(buf
+ len
, buf_size
- len
, s
);
889 /* memory management */
895 static inline void tcc_free(void *ptr
)
898 mem_cur_size
-= malloc_usable_size(ptr
);
903 static void *tcc_malloc(unsigned long size
)
908 error("memory full");
910 mem_cur_size
+= malloc_usable_size(ptr
);
911 if (mem_cur_size
> mem_max_size
)
912 mem_max_size
= mem_cur_size
;
917 static void *tcc_mallocz(unsigned long size
)
920 ptr
= tcc_malloc(size
);
921 memset(ptr
, 0, size
);
925 static inline void *tcc_realloc(void *ptr
, unsigned long size
)
929 mem_cur_size
-= malloc_usable_size(ptr
);
931 ptr1
= realloc(ptr
, size
);
933 /* NOTE: count not correct if alloc error, but not critical */
934 mem_cur_size
+= malloc_usable_size(ptr1
);
935 if (mem_cur_size
> mem_max_size
)
936 mem_max_size
= mem_cur_size
;
941 static char *tcc_strdup(const char *str
)
944 ptr
= tcc_malloc(strlen(str
) + 1);
949 #define free(p) use_tcc_free(p)
950 #define malloc(s) use_tcc_malloc(s)
951 #define realloc(p, s) use_tcc_realloc(p, s)
953 static void dynarray_add(void ***ptab
, int *nb_ptr
, void *data
)
960 /* every power of two we double array size */
961 if ((nb
& (nb
- 1)) == 0) {
966 pp
= tcc_realloc(pp
, nb_alloc
* sizeof(void *));
968 error("memory full");
975 Section
*new_section(TCCState
*s1
, const char *name
, int sh_type
, int sh_flags
)
979 sec
= tcc_mallocz(sizeof(Section
) + strlen(name
));
980 strcpy(sec
->name
, name
);
981 sec
->sh_type
= sh_type
;
982 sec
->sh_flags
= sh_flags
;
989 sec
->sh_addralign
= 4;
992 sec
->sh_addralign
= 1;
995 sec
->sh_addralign
= 32; /* default conservative alignment */
999 /* only add section if not private */
1000 if (!(sh_flags
& SHF_PRIVATE
)) {
1001 sec
->sh_num
= s1
->nb_sections
;
1002 dynarray_add((void ***)&s1
->sections
, &s1
->nb_sections
, sec
);
1007 static void free_section(Section
*s
)
1013 /* realloc section and set its content to zero */
1014 static void section_realloc(Section
*sec
, unsigned long new_size
)
1017 unsigned char *data
;
1019 size
= sec
->data_allocated
;
1022 while (size
< new_size
)
1024 data
= tcc_realloc(sec
->data
, size
);
1026 error("memory full");
1027 memset(data
+ sec
->data_allocated
, 0, size
- sec
->data_allocated
);
1029 sec
->data_allocated
= size
;
1032 /* reserve at least 'size' bytes in section 'sec' from
1033 sec->data_offset. */
1034 static void *section_ptr_add(Section
*sec
, unsigned long size
)
1036 unsigned long offset
, offset1
;
1038 offset
= sec
->data_offset
;
1039 offset1
= offset
+ size
;
1040 if (offset1
> sec
->data_allocated
)
1041 section_realloc(sec
, offset1
);
1042 sec
->data_offset
= offset1
;
1043 return sec
->data
+ offset
;
1046 /* return a reference to a section, and create it if it does not
1048 Section
*find_section(TCCState
*s1
, const char *name
)
1052 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1053 sec
= s1
->sections
[i
];
1054 if (!strcmp(name
, sec
->name
))
1057 /* sections are created as PROGBITS */
1058 return new_section(s1
, name
, SHT_PROGBITS
, SHF_ALLOC
);
1061 /* update sym->c so that it points to an external symbol in section
1062 'section' with value 'value' */
1063 static void put_extern_sym(Sym
*sym
, Section
*section
,
1064 unsigned long value
, unsigned long size
)
1066 int sym_type
, sym_bind
, sh_num
, info
;
1071 sh_num
= section
->sh_num
;
1075 if ((sym
->type
.t
& VT_BTYPE
) == VT_FUNC
)
1076 sym_type
= STT_FUNC
;
1078 sym_type
= STT_OBJECT
;
1079 if (sym
->type
.t
& VT_STATIC
)
1080 sym_bind
= STB_LOCAL
;
1082 sym_bind
= STB_GLOBAL
;
1084 name
= get_tok_str(sym
->v
, NULL
);
1085 #ifdef CONFIG_TCC_BCHECK
1086 if (do_bounds_check
) {
1089 /* XXX: avoid doing that for statics ? */
1090 /* if bound checking is activated, we change some function
1091 names by adding the "__bound" prefix */
1094 /* XXX: we rely only on malloc hooks */
1106 strcpy(buf
, "__bound_");
1113 info
= ELF32_ST_INFO(sym_bind
, sym_type
);
1114 sym
->c
= add_elf_sym(symtab_section
, value
, size
, info
, sh_num
, name
);
1116 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
1117 esym
->st_value
= value
;
1118 esym
->st_size
= size
;
1119 esym
->st_shndx
= sh_num
;
1123 /* add a new relocation entry to symbol 'sym' in section 's' */
1124 static void greloc(Section
*s
, Sym
*sym
, unsigned long offset
, int type
)
1127 put_extern_sym(sym
, NULL
, 0, 0);
1128 /* now we can add ELF relocation info */
1129 put_elf_reloc(symtab_section
, s
, offset
, type
, sym
->c
);
1132 static inline int isid(int c
)
1134 return (c
>= 'a' && c
<= 'z') ||
1135 (c
>= 'A' && c
<= 'Z') ||
1139 static inline int isnum(int c
)
1141 return c
>= '0' && c
<= '9';
1144 static inline int isoct(int c
)
1146 return c
>= '0' && c
<= '7';
1149 static inline int toup(int c
)
1151 if (c
>= 'a' && c
<= 'z')
1152 return c
- 'a' + 'A';
1157 static void strcat_vprintf(char *buf
, int buf_size
, const char *fmt
, va_list ap
)
1161 vsnprintf(buf
+ len
, buf_size
- len
, fmt
, ap
);
1164 static void strcat_printf(char *buf
, int buf_size
, const char *fmt
, ...)
1168 strcat_vprintf(buf
, buf_size
, fmt
, ap
);
1172 void error1(TCCState
*s1
, int is_warning
, const char *fmt
, va_list ap
)
1179 for(f
= s1
->include_stack
; f
< s1
->include_stack_ptr
; f
++)
1180 strcat_printf(buf
, sizeof(buf
), "In file included from %s:%d:\n",
1181 (*f
)->filename
, (*f
)->line_num
);
1182 if (file
->line_num
> 0) {
1183 strcat_printf(buf
, sizeof(buf
),
1184 "%s:%d: ", file
->filename
, file
->line_num
);
1186 strcat_printf(buf
, sizeof(buf
),
1187 "%s: ", file
->filename
);
1190 strcat_printf(buf
, sizeof(buf
),
1194 strcat_printf(buf
, sizeof(buf
), "warning: ");
1195 strcat_vprintf(buf
, sizeof(buf
), fmt
, ap
);
1197 if (!s1
->error_func
) {
1198 /* default case: stderr */
1199 fprintf(stderr
, "%s\n", buf
);
1201 s1
->error_func(s1
->error_opaque
, buf
);
1203 if (!is_warning
|| s1
->warn_error
)
1208 void tcc_set_error_func(TCCState
*s
, void *error_opaque
,
1209 void (*error_func
)(void *opaque
, const char *msg
))
1211 s
->error_opaque
= error_opaque
;
1212 s
->error_func
= error_func
;
1216 /* error without aborting current compilation */
1217 void error_noabort(const char *fmt
, ...)
1219 TCCState
*s1
= tcc_state
;
1223 error1(s1
, 0, fmt
, ap
);
1227 void error(const char *fmt
, ...)
1229 TCCState
*s1
= tcc_state
;
1233 error1(s1
, 0, fmt
, ap
);
1235 /* better than nothing: in some cases, we accept to handle errors */
1236 if (s1
->error_set_jmp_enabled
) {
1237 longjmp(s1
->error_jmp_buf
, 1);
1239 /* XXX: eliminate this someday */
1244 void expect(const char *msg
)
1246 error("%s expected", msg
);
1249 void warning(const char *fmt
, ...)
1251 TCCState
*s1
= tcc_state
;
1258 error1(s1
, 1, fmt
, ap
);
1265 error("'%c' expected", c
);
1269 static void test_lvalue(void)
1271 if (!(vtop
->r
& VT_LVAL
))
1275 /* allocate a new token */
1276 static TokenSym
*tok_alloc_new(TokenSym
**pts
, const char *str
, int len
)
1278 TokenSym
*ts
, **ptable
;
1281 if (tok_ident
>= SYM_FIRST_ANOM
)
1282 error("memory full");
1284 /* expand token table if needed */
1285 i
= tok_ident
- TOK_IDENT
;
1286 if ((i
% TOK_ALLOC_INCR
) == 0) {
1287 ptable
= tcc_realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
1289 error("memory full");
1290 table_ident
= ptable
;
1293 ts
= tcc_malloc(sizeof(TokenSym
) + len
);
1294 table_ident
[i
] = ts
;
1295 ts
->tok
= tok_ident
++;
1296 ts
->sym_define
= NULL
;
1297 ts
->sym_label
= NULL
;
1298 ts
->sym_struct
= NULL
;
1299 ts
->sym_identifier
= NULL
;
1301 ts
->hash_next
= NULL
;
1302 memcpy(ts
->str
, str
, len
);
1303 ts
->str
[len
] = '\0';
1308 #define TOK_HASH_INIT 1
1309 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1311 /* find a token and add it if not found */
1312 static TokenSym
*tok_alloc(const char *str
, int len
)
1314 TokenSym
*ts
, **pts
;
1320 h
= TOK_HASH_FUNC(h
, ((unsigned char *)str
)[i
]);
1321 h
&= (TOK_HASH_SIZE
- 1);
1323 pts
= &hash_ident
[h
];
1328 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
1330 pts
= &(ts
->hash_next
);
1332 return tok_alloc_new(pts
, str
, len
);
1335 /* CString handling */
1337 static void cstr_realloc(CString
*cstr
, int new_size
)
1342 size
= cstr
->size_allocated
;
1344 size
= 8; /* no need to allocate a too small first string */
1345 while (size
< new_size
)
1347 data
= tcc_realloc(cstr
->data_allocated
, size
);
1349 error("memory full");
1350 cstr
->data_allocated
= data
;
1351 cstr
->size_allocated
= size
;
1356 static void cstr_ccat(CString
*cstr
, int ch
)
1359 size
= cstr
->size
+ 1;
1360 if (size
> cstr
->size_allocated
)
1361 cstr_realloc(cstr
, size
);
1362 ((unsigned char *)cstr
->data
)[size
- 1] = ch
;
1366 static void cstr_cat(CString
*cstr
, const char *str
)
1378 /* add a wide char */
1379 static void cstr_wccat(CString
*cstr
, int ch
)
1382 size
= cstr
->size
+ sizeof(int);
1383 if (size
> cstr
->size_allocated
)
1384 cstr_realloc(cstr
, size
);
1385 *(int *)(((unsigned char *)cstr
->data
) + size
- sizeof(int)) = ch
;
1389 static void cstr_new(CString
*cstr
)
1391 memset(cstr
, 0, sizeof(CString
));
1394 /* free string and reset it to NULL */
1395 static void cstr_free(CString
*cstr
)
1397 tcc_free(cstr
->data_allocated
);
1401 #define cstr_reset(cstr) cstr_free(cstr)
1403 static CString
*cstr_dup(CString
*cstr1
)
1408 cstr
= tcc_malloc(sizeof(CString
));
1411 cstr
->size_allocated
= size
;
1412 cstr
->data_allocated
= tcc_malloc(size
);
1413 cstr
->data
= cstr
->data_allocated
;
1414 memcpy(cstr
->data_allocated
, cstr1
->data_allocated
, size
);
1418 /* XXX: unicode ? */
1419 static void add_char(CString
*cstr
, int c
)
1421 if (c
== '\'' || c
== '\"' || c
== '\\') {
1422 /* XXX: could be more precise if char or string */
1423 cstr_ccat(cstr
, '\\');
1425 if (c
>= 32 && c
<= 126) {
1428 cstr_ccat(cstr
, '\\');
1430 cstr_ccat(cstr
, 'n');
1432 cstr_ccat(cstr
, '0' + ((c
>> 6) & 7));
1433 cstr_ccat(cstr
, '0' + ((c
>> 3) & 7));
1434 cstr_ccat(cstr
, '0' + (c
& 7));
1439 /* XXX: buffer overflow */
1440 /* XXX: float tokens */
1441 char *get_tok_str(int v
, CValue
*cv
)
1443 static char buf
[STRING_MAX_SIZE
+ 1];
1444 static CString cstr_buf
;
1450 /* NOTE: to go faster, we give a fixed buffer for small strings */
1451 cstr_reset(&cstr_buf
);
1452 cstr_buf
.data
= buf
;
1453 cstr_buf
.size_allocated
= sizeof(buf
);
1459 /* XXX: not quite exact, but only useful for testing */
1460 sprintf(p
, "%u", cv
->ui
);
1464 /* XXX: not quite exact, but only useful for testing */
1465 sprintf(p
, "%Lu", cv
->ull
);
1469 cstr_ccat(&cstr_buf
, '\'');
1470 add_char(&cstr_buf
, cv
->i
);
1471 cstr_ccat(&cstr_buf
, '\'');
1472 cstr_ccat(&cstr_buf
, '\0');
1476 len
= cstr
->size
- 1;
1478 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1479 cstr_ccat(&cstr_buf
, '\0');
1484 cstr_ccat(&cstr_buf
, '\"');
1486 len
= cstr
->size
- 1;
1488 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1490 len
= (cstr
->size
/ sizeof(int)) - 1;
1492 add_char(&cstr_buf
, ((int *)cstr
->data
)[i
]);
1494 cstr_ccat(&cstr_buf
, '\"');
1495 cstr_ccat(&cstr_buf
, '\0');
1504 return strcpy(p
, "<<=");
1506 return strcpy(p
, ">>=");
1508 if (v
< TOK_IDENT
) {
1509 /* search in two bytes table */
1523 } else if (v
< tok_ident
) {
1524 return table_ident
[v
- TOK_IDENT
]->str
;
1525 } else if (v
>= SYM_FIRST_ANOM
) {
1526 /* special name for anonymous symbol */
1527 sprintf(p
, "L.%u", v
- SYM_FIRST_ANOM
);
1529 /* should never happen */
1534 return cstr_buf
.data
;
1537 /* push, without hashing */
1538 static Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
1541 s
= tcc_malloc(sizeof(Sym
));
1552 /* find a symbol and return its associated structure. 's' is the top
1553 of the symbol stack */
1554 static Sym
*sym_find2(Sym
*s
, int v
)
1564 /* structure lookup */
1565 static inline Sym
*struct_find(int v
)
1568 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1570 return table_ident
[v
]->sym_struct
;
1573 /* find an identifier */
1574 static inline Sym
*sym_find(int v
)
1577 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1579 return table_ident
[v
]->sym_identifier
;
1582 /* push a given symbol on the symbol stack */
1583 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
)
1592 s
= sym_push2(ps
, v
, type
->t
, c
);
1593 s
->type
.ref
= type
->ref
;
1595 /* don't record fields or anonymous symbols */
1597 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1598 /* record symbol in token array */
1599 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1601 ps
= &ts
->sym_struct
;
1603 ps
= &ts
->sym_identifier
;
1610 /* push a global identifier */
1611 static Sym
*global_identifier_push(int v
, int t
, int c
)
1614 s
= sym_push2(&global_stack
, v
, t
, c
);
1615 /* don't record anonymous symbol */
1616 if (v
< SYM_FIRST_ANOM
) {
1617 ps
= &table_ident
[v
- TOK_IDENT
]->sym_identifier
;
1618 /* modify the top most local identifier, so that
1619 sym_identifier will point to 's' when popped */
1621 ps
= &(*ps
)->prev_tok
;
1628 /* pop symbols until top reaches 'b' */
1629 static void sym_pop(Sym
**ptop
, Sym
*b
)
1639 /* remove symbol in token array */
1641 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1642 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1644 ps
= &ts
->sym_struct
;
1646 ps
= &ts
->sym_identifier
;
1657 BufferedFile
*tcc_open(TCCState
*s1
, const char *filename
)
1662 fd
= open(filename
, O_RDONLY
);
1665 bf
= tcc_malloc(sizeof(BufferedFile
));
1671 bf
->buf_ptr
= bf
->buffer
;
1672 bf
->buf_end
= bf
->buffer
;
1673 bf
->buffer
[0] = CH_EOB
; /* put eob symbol */
1674 pstrcpy(bf
->filename
, sizeof(bf
->filename
), filename
);
1676 bf
->ifndef_macro
= 0;
1677 bf
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
1678 // printf("opening '%s'\n", filename);
1682 void tcc_close(BufferedFile
*bf
)
1684 total_lines
+= bf
->line_num
;
1689 /* fill input buffer and peek next char */
1690 static int tcc_peekc_slow(BufferedFile
*bf
)
1693 /* only tries to read if really end of buffer */
1694 if (bf
->buf_ptr
>= bf
->buf_end
) {
1696 #if defined(PARSE_DEBUG)
1701 len
= read(bf
->fd
, bf
->buffer
, len
);
1708 bf
->buf_ptr
= bf
->buffer
;
1709 bf
->buf_end
= bf
->buffer
+ len
;
1710 *bf
->buf_end
= CH_EOB
;
1712 if (bf
->buf_ptr
< bf
->buf_end
) {
1713 return bf
->buf_ptr
[0];
1715 bf
->buf_ptr
= bf
->buf_end
;
1720 /* return the current character, handling end of block if necessary
1722 static int handle_eob(void)
1724 return tcc_peekc_slow(file
);
1727 /* read next char from current input file and handle end of input buffer */
1728 static inline void inp(void)
1730 ch
= *(++(file
->buf_ptr
));
1731 /* end of buffer/file handling */
1736 /* handle '\[\r]\n' */
1737 static void handle_stray(void)
1739 while (ch
== '\\') {
1744 } else if (ch
== '\r') {
1752 error("stray '\\' in program");
1757 /* skip the stray and handle the \\n case. Output an error if
1758 incorrect char after the stray */
1759 static int handle_stray1(uint8_t *p
)
1763 if (p
>= file
->buf_end
) {
1780 /* handle just the EOB case, but not stray */
1781 #define PEEKC_EOB(c, p)\
1792 /* handle the complicated stray case */
1793 #define PEEKC(c, p)\
1798 c = handle_stray1(p);\
1803 /* input with '\[\r]\n' handling. Note that this function cannot
1804 handle other characters after '\', so you cannot call it inside
1805 strings or comments */
1806 static void minp(void)
1814 /* single line C++ comments */
1815 static uint8_t *parse_line_comment(uint8_t *p
)
1822 if (c
== '\n' || c
== CH_EOF
) {
1824 } else if (c
== '\\') {
1829 } else if (c
== '\r') {
1844 static uint8_t *parse_comment(uint8_t *p
)
1850 /* fast skip loop */
1853 if (c
== '\n' || c
== '*' || c
== '\\')
1857 if (c
== '\n' || c
== '*' || c
== '\\')
1861 /* now we can handle all the cases */
1865 } else if (c
== '*') {
1871 } else if (c
== '/') {
1872 goto end_of_comment
;
1873 } else if (c
== '\\') {
1878 /* skip '\[\r]\n', otherwise just skip the stray */
1884 } else if (c
== '\r') {
1901 /* stray, eob or eof */
1906 error("unexpected end of file in comment");
1907 } else if (c
== '\\') {
1919 /* space exlcuding newline */
1920 static inline int is_space(int ch
)
1922 return ch
== ' ' || ch
== '\t' || ch
== '\v' || ch
== '\f' || ch
== '\r';
1925 static inline void skip_spaces(void)
1927 while (is_space(ch
))
1931 /* parse a string without interpreting escapes */
1932 static uint8_t *parse_pp_string(uint8_t *p
,
1933 int sep
, CString
*str
)
1941 } else if (c
== '\\') {
1946 unterminated_string
:
1947 /* XXX: indicate line number of start of string */
1948 error("missing terminating %c character", sep
);
1949 } else if (c
== '\\') {
1950 /* escape : just skip \[\r]\n */
1955 } else if (c
== '\r') {
1958 expect("'\n' after '\r'");
1961 } else if (c
== CH_EOF
) {
1962 goto unterminated_string
;
1965 cstr_ccat(str
, '\\');
1971 } else if (c
== '\n') {
1974 } else if (c
== '\r') {
1977 cstr_ccat(str
, '\r');
1993 /* skip block of text until #else, #elif or #endif. skip also pairs of
1995 void preprocess_skip(void)
1997 int a
, start_of_line
, c
;
2024 } else if (c
== '\\') {
2025 /* XXX: incorrect: should not give an error */
2026 ch
= file
->buf_ptr
[0];
2034 p
= parse_pp_string(p
, c
, NULL
);
2043 p
= parse_comment(p
);
2044 } else if (ch
== '/') {
2045 p
= parse_line_comment(p
);
2051 if (start_of_line
) {
2056 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
2058 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
2060 else if (tok
== TOK_ENDIF
)
2074 /* ParseState handling */
2076 /* XXX: currently, no include file info is stored. Thus, we cannot display
2077 accurate messages if the function or data definition spans multiple
2080 /* save current parse state in 's' */
2081 void save_parse_state(ParseState
*s
)
2083 s
->line_num
= file
->line_num
;
2084 s
->macro_ptr
= macro_ptr
;
2089 /* restore parse state from 's' */
2090 void restore_parse_state(ParseState
*s
)
2092 file
->line_num
= s
->line_num
;
2093 macro_ptr
= s
->macro_ptr
;
2098 /* return the number of additional 'ints' necessary to store the
2100 static inline int tok_ext_size(int t
)
2119 return LDOUBLE_SIZE
/ 4;
2125 /* token string handling */
2127 static inline void tok_str_new(TokenString
*s
)
2131 s
->allocated_len
= 0;
2132 s
->last_line_num
= -1;
2135 static void tok_str_free(int *str
)
2144 /* NOTE: we test zero separately so that GCC can generate a
2145 table for the following switch */
2160 /* XXX: use a macro to be portable on 64 bit ? */
2161 cstr
= (CString
*)p
[1];
2172 p
+= 1 + (LDOUBLE_SIZE
/ 4);
2182 static int *tok_str_realloc(TokenString
*s
)
2186 len
= s
->allocated_len
+ TOK_STR_ALLOC_INCR
;
2187 str
= tcc_realloc(s
->str
, len
* sizeof(int));
2189 error("memory full");
2190 s
->allocated_len
= len
;
2195 static void tok_str_add(TokenString
*s
, int t
)
2201 if (len
>= s
->allocated_len
)
2202 str
= tok_str_realloc(s
);
2207 static void tok_str_add2(TokenString
*s
, int t
, CValue
*cv
)
2214 /* allocate space for worst case */
2215 if (len
+ TOK_MAX_SIZE
> s
->allocated_len
)
2216 str
= tok_str_realloc(s
);
2225 str
[len
++] = cv
->tab
[0];
2230 str
[len
++] = (int)cstr_dup(cv
->cstr
);
2235 #if LDOUBLE_SIZE == 8
2238 str
[len
++] = cv
->tab
[0];
2239 str
[len
++] = cv
->tab
[1];
2241 #if LDOUBLE_SIZE == 12
2243 str
[len
++] = cv
->tab
[0];
2244 str
[len
++] = cv
->tab
[1];
2245 str
[len
++] = cv
->tab
[2];
2246 #elif LDOUBLE_SIZE != 8
2247 #error add long double size support
2256 /* add the current parse token in token string 's' */
2257 static void tok_str_add_tok(TokenString
*s
)
2261 /* save line number info */
2262 if (file
->line_num
!= s
->last_line_num
) {
2263 s
->last_line_num
= file
->line_num
;
2264 cval
.i
= s
->last_line_num
;
2265 tok_str_add2(s
, TOK_LINENUM
, &cval
);
2267 tok_str_add2(s
, tok
, &tokc
);
2270 #if LDOUBLE_SIZE == 12
2271 #define LDOUBLE_GET(p, cv) \
2275 #elif LDOUBLE_SIZE == 8
2276 #define LDOUBLE_GET(p, cv) \
2280 #error add long double size support
2284 /* get a token from an integer array and increment pointer
2285 accordingly. we code it as a macro to avoid pointer aliasing. */
2286 #define TOK_GET(t, p, cv) \
2308 case TOK_CLDOUBLE: \
2309 LDOUBLE_GET(p, cv); \
2310 p += LDOUBLE_SIZE / 4; \
2317 /* defines handling */
2318 static inline void define_push(int v
, int macro_type
, int *str
, Sym
*first_arg
)
2322 s
= sym_push2(&define_stack
, v
, macro_type
, (int)str
);
2323 s
->next
= first_arg
;
2324 table_ident
[v
- TOK_IDENT
]->sym_define
= s
;
2327 /* undefined a define symbol. Its name is just set to zero */
2328 static void define_undef(Sym
*s
)
2332 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2333 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2337 static inline Sym
*define_find(int v
)
2340 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2342 return table_ident
[v
]->sym_define
;
2345 /* free define stack until top reaches 'b' */
2346 static void free_defines(Sym
*b
)
2354 /* do not free args or predefined defines */
2356 tok_str_free((int *)top
->c
);
2358 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2359 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2367 static Sym
*label_find(int v
)
2370 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2372 return table_ident
[v
]->sym_label
;
2375 static Sym
*label_push(Sym
**ptop
, int v
, int flags
)
2378 s
= sym_push2(ptop
, v
, 0, 0);
2380 ps
= &table_ident
[v
- TOK_IDENT
]->sym_label
;
2381 if (ptop
== &global_label_stack
) {
2382 /* modify the top most local identifier, so that
2383 sym_identifier will point to 's' when popped */
2385 ps
= &(*ps
)->prev_tok
;
2392 /* pop labels until element last is reached. Look if any labels are
2393 undefined. Define symbols if '&&label' was used. */
2394 static void label_pop(Sym
**ptop
, Sym
*slast
)
2397 for(s
= *ptop
; s
!= slast
; s
= s1
) {
2399 if (s
->r
== LABEL_DECLARED
) {
2400 warning("label '%s' declared but not used", get_tok_str(s
->v
, NULL
));
2401 } else if (s
->r
== LABEL_FORWARD
) {
2402 error("label '%s' used but not defined",
2403 get_tok_str(s
->v
, NULL
));
2406 /* define corresponding symbol. A size of
2408 put_extern_sym(s
, cur_text_section
, (long)s
->next
, 1);
2412 table_ident
[s
->v
- TOK_IDENT
]->sym_label
= s
->prev_tok
;
2418 /* eval an expression for #if/#elif */
2419 static int expr_preprocess(void)
2425 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2426 next(); /* do macro subst */
2427 if (tok
== TOK_DEFINED
) {
2432 c
= define_find(tok
) != 0;
2437 } else if (tok
>= TOK_IDENT
) {
2438 /* if undefined macro */
2442 tok_str_add_tok(&str
);
2444 tok_str_add(&str
, -1); /* simulate end of file */
2445 tok_str_add(&str
, 0);
2446 /* now evaluate C constant expression */
2447 macro_ptr
= str
.str
;
2451 tok_str_free(str
.str
);
2455 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2456 static void tok_print(int *str
)
2462 TOK_GET(t
, str
, cval
);
2465 printf(" %s", get_tok_str(t
, &cval
));
2471 /* parse after #define */
2472 static void parse_define(void)
2474 Sym
*s
, *first
, **ps
;
2475 int v
, t
, varg
, is_vaargs
, c
;
2480 error("invalid macro name '%s'", get_tok_str(tok
, &tokc
));
2481 /* XXX: should check if same macro (ANSI) */
2484 /* '(' must be just after macro definition for MACRO_FUNC */
2485 c
= file
->buf_ptr
[0];
2487 c
= handle_stray1(file
->buf_ptr
);
2492 while (tok
!= ')') {
2496 if (varg
== TOK_DOTS
) {
2497 varg
= TOK___VA_ARGS__
;
2499 } else if (tok
== TOK_DOTS
&& gnu_ext
) {
2503 if (varg
< TOK_IDENT
)
2504 error("badly punctuated parameter list");
2505 s
= sym_push2(&define_stack
, varg
| SYM_FIELD
, is_vaargs
, 0);
2516 /* EOF testing necessary for '-D' handling */
2517 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2518 tok_str_add2(&str
, tok
, &tokc
);
2521 tok_str_add(&str
, 0);
2523 printf("define %s %d: ", get_tok_str(v
, NULL
), t
);
2526 define_push(v
, t
, str
.str
, first
);
2529 /* XXX: use a token or a hash table to accelerate matching ? */
2530 static CachedInclude
*search_cached_include(TCCState
*s1
,
2531 int type
, const char *filename
)
2536 for(i
= 0;i
< s1
->nb_cached_includes
; i
++) {
2537 e
= s1
->cached_includes
[i
];
2538 if (e
->type
== type
&& !strcmp(e
->filename
, filename
))
2544 static inline void add_cached_include(TCCState
*s1
, int type
,
2545 const char *filename
, int ifndef_macro
)
2549 if (search_cached_include(s1
, type
, filename
))
2552 printf("adding cached '%s' %s\n", filename
, get_tok_str(ifndef_macro
, NULL
));
2554 e
= tcc_malloc(sizeof(CachedInclude
) + strlen(filename
));
2558 strcpy(e
->filename
, filename
);
2559 e
->ifndef_macro
= ifndef_macro
;
2560 dynarray_add((void ***)&s1
->cached_includes
, &s1
->nb_cached_includes
, e
);
2563 /* is_bof is true if first non space token at beginning of file */
2564 static void preprocess(int is_bof
)
2566 TCCState
*s1
= tcc_state
;
2567 int size
, i
, c
, n
, saved_parse_flags
;
2568 char buf
[1024], *q
, *p
;
2574 saved_parse_flags
= parse_flags
;
2575 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
|
2576 PARSE_FLAG_LINEFEED
;
2586 s
= define_find(tok
);
2587 /* undefine symbol by putting an invalid name */
2592 ch
= file
->buf_ptr
[0];
2593 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2598 } else if (ch
== '\"') {
2601 /* XXX: better stray handling */
2604 while (ch
!= c
&& ch
!= '\n' && ch
!= CH_EOF
) {
2605 if ((q
- buf
) < sizeof(buf
) - 1)
2612 /* eat all spaces and comments after include */
2613 /* XXX: slightly incorrect */
2614 while (ch1
!= '\n' && ch1
!= CH_EOF
)
2618 /* computed #include : either we have only strings or
2619 we have anything enclosed in '<>' */
2622 if (tok
== TOK_STR
) {
2623 while (tok
!= TOK_LINEFEED
) {
2624 if (tok
!= TOK_STR
) {
2626 error("'#include' expects \"FILENAME\" or <FILENAME>");
2628 pstrcat(buf
, sizeof(buf
), (char *)tokc
.cstr
->data
);
2634 while (tok
!= TOK_LINEFEED
) {
2635 pstrcat(buf
, sizeof(buf
), get_tok_str(tok
, &tokc
));
2639 /* check syntax and remove '<>' */
2640 if (len
< 2 || buf
[0] != '<' || buf
[len
- 1] != '>')
2641 goto include_syntax
;
2642 memmove(buf
, buf
+ 1, len
- 2);
2643 buf
[len
- 2] = '\0';
2648 e
= search_cached_include(s1
, c
, buf
);
2649 if (e
&& define_find(e
->ifndef_macro
)) {
2650 /* no need to parse the include because the 'ifndef macro'
2653 printf("%s: skipping %s\n", file
->filename
, buf
);
2657 /* first search in current dir if "header.h" */
2659 p
= strrchr(file
->filename
, '/');
2661 size
= p
+ 1 - file
->filename
;
2662 if (size
> sizeof(buf1
) - 1)
2663 size
= sizeof(buf1
) - 1;
2664 memcpy(buf1
, file
->filename
, size
);
2666 pstrcat(buf1
, sizeof(buf1
), buf
);
2667 f
= tcc_open(s1
, buf1
);
2671 if (s1
->include_stack_ptr
>= s1
->include_stack
+ INCLUDE_STACK_SIZE
)
2672 error("#include recursion too deep");
2673 /* now search in all the include paths */
2674 n
= s1
->nb_include_paths
+ s1
->nb_sysinclude_paths
;
2675 for(i
= 0; i
< n
; i
++) {
2677 if (i
< s1
->nb_include_paths
)
2678 path
= s1
->include_paths
[i
];
2680 path
= s1
->sysinclude_paths
[i
- s1
->nb_include_paths
];
2681 pstrcpy(buf1
, sizeof(buf1
), path
);
2682 pstrcat(buf1
, sizeof(buf1
), "/");
2683 pstrcat(buf1
, sizeof(buf1
), buf
);
2684 f
= tcc_open(s1
, buf1
);
2688 error("include file '%s' not found", buf
);
2692 printf("%s: including %s\n", file
->filename
, buf1
);
2695 pstrcpy(f
->inc_filename
, sizeof(f
->inc_filename
), buf
);
2696 /* push current file in stack */
2697 /* XXX: fix current line init */
2698 *s1
->include_stack_ptr
++ = file
;
2700 /* add include file debug info */
2702 put_stabs(file
->filename
, N_BINCL
, 0, 0, 0);
2704 tok_flags
|= TOK_FLAG_BOF
| TOK_FLAG_BOL
;
2705 ch
= file
->buf_ptr
[0];
2713 c
= expr_preprocess();
2719 if (tok
< TOK_IDENT
)
2720 error("invalid argument for '#if%sdef'", c
? "n" : "");
2724 printf("#ifndef %s\n", get_tok_str(tok
, NULL
));
2726 file
->ifndef_macro
= tok
;
2729 c
= (define_find(tok
) != 0) ^ c
;
2731 if (s1
->ifdef_stack_ptr
>= s1
->ifdef_stack
+ IFDEF_STACK_SIZE
)
2732 error("memory full");
2733 *s1
->ifdef_stack_ptr
++ = c
;
2736 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
2737 error("#else without matching #if");
2738 if (s1
->ifdef_stack_ptr
[-1] & 2)
2739 error("#else after #else");
2740 c
= (s1
->ifdef_stack_ptr
[-1] ^= 3);
2743 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
2744 error("#elif without matching #if");
2745 c
= s1
->ifdef_stack_ptr
[-1];
2747 error("#elif after #else");
2748 /* last #if/#elif expression was true: we skip */
2751 c
= expr_preprocess();
2752 s1
->ifdef_stack_ptr
[-1] = c
;
2762 if (s1
->ifdef_stack_ptr
<= file
->ifdef_stack_ptr
)
2763 error("#endif without matching #if");
2764 s1
->ifdef_stack_ptr
--;
2765 /* '#ifndef macro' was at the start of file. Now we check if
2766 an '#endif' is exactly at the end of file */
2767 if (file
->ifndef_macro
&&
2768 s1
->ifdef_stack_ptr
== file
->ifdef_stack_ptr
) {
2769 file
->ifndef_macro_saved
= file
->ifndef_macro
;
2770 /* need to set to zero to avoid false matches if another
2771 #ifndef at middle of file */
2772 file
->ifndef_macro
= 0;
2773 while (tok
!= TOK_LINEFEED
)
2775 tok_flags
|= TOK_FLAG_ENDIF
;
2781 if (tok
!= TOK_CINT
)
2783 file
->line_num
= tokc
.i
- 1; /* the line number will be incremented after */
2785 if (tok
!= TOK_LINEFEED
) {
2788 pstrcpy(file
->filename
, sizeof(file
->filename
),
2789 (char *)tokc
.cstr
->data
);
2795 ch
= file
->buf_ptr
[0];
2798 while (ch
!= '\n' && ch
!= CH_EOF
) {
2799 if ((q
- buf
) < sizeof(buf
) - 1)
2805 error("#error %s", buf
);
2807 warning("#warning %s", buf
);
2813 if (tok
== TOK_LINEFEED
|| tok
== '!' || tok
== TOK_CINT
) {
2814 /* '!' is ignored to allow C scripts. numbers are ignored
2815 to emulate cpp behaviour */
2817 error("invalid preprocessing directive #%s", get_tok_str(tok
, &tokc
));
2821 /* ignore other preprocess commands or #! for C scripts */
2822 while (tok
!= TOK_LINEFEED
)
2825 parse_flags
= saved_parse_flags
;
2828 /* evaluate escape codes in a string. */
2829 static void parse_escape_string(CString
*outstr
, const uint8_t *buf
, int is_long
)
2844 case '0': case '1': case '2': case '3':
2845 case '4': case '5': case '6': case '7':
2846 /* at most three octal digits */
2851 n
= n
* 8 + c
- '0';
2855 n
= n
* 8 + c
- '0';
2860 goto add_char_nonext
;
2866 if (c
>= 'a' && c
<= 'f')
2868 else if (c
>= 'A' && c
<= 'F')
2878 goto add_char_nonext
;
2902 goto invalid_escape
;
2912 if (c
>= '!' && c
<= '~')
2913 warning("unknown escape sequence: \'\\%c\'", c
);
2915 warning("unknown escape sequence: \'\\x%x\'", c
);
2922 cstr_ccat(outstr
, c
);
2924 cstr_wccat(outstr
, c
);
2926 /* add a trailing '\0' */
2928 cstr_ccat(outstr
, '\0');
2930 cstr_wccat(outstr
, '\0');
2933 /* we use 64 bit numbers */
2936 /* bn = (bn << shift) | or_val */
2937 void bn_lshift(unsigned int *bn
, int shift
, int or_val
)
2941 for(i
=0;i
<BN_SIZE
;i
++) {
2943 bn
[i
] = (v
<< shift
) | or_val
;
2944 or_val
= v
>> (32 - shift
);
2948 void bn_zero(unsigned int *bn
)
2951 for(i
=0;i
<BN_SIZE
;i
++) {
2956 /* parse number in null terminated string 'p' and return it in the
2958 void parse_number(const char *p
)
2960 int b
, t
, shift
, frac_bits
, s
, exp_val
, ch
;
2962 unsigned int bn
[BN_SIZE
];
2973 goto float_frac_parse
;
2974 } else if (t
== '0') {
2975 if (ch
== 'x' || ch
== 'X') {
2979 } else if (tcc_ext
&& (ch
== 'b' || ch
== 'B')) {
2985 /* parse all digits. cannot check octal numbers at this stage
2986 because of floating point constants */
2988 if (ch
>= 'a' && ch
<= 'f')
2990 else if (ch
>= 'A' && ch
<= 'F')
2998 if (q
>= token_buf
+ STRING_MAX_SIZE
) {
3000 error("number too long");
3006 ((ch
== 'e' || ch
== 'E') && b
== 10) ||
3007 ((ch
== 'p' || ch
== 'P') && (b
== 16 || b
== 2))) {
3009 /* NOTE: strtox should support that for hexa numbers, but
3010 non ISOC99 libcs do not support it, so we prefer to do
3012 /* hexadecimal or binary floats */
3013 /* XXX: handle overflows */
3025 } else if (t
>= 'a') {
3027 } else if (t
>= 'A') {
3032 bn_lshift(bn
, shift
, t
);
3039 if (t
>= 'a' && t
<= 'f') {
3041 } else if (t
>= 'A' && t
<= 'F') {
3043 } else if (t
>= '0' && t
<= '9') {
3049 error("invalid digit");
3050 bn_lshift(bn
, shift
, t
);
3055 if (ch
!= 'p' && ch
!= 'P')
3062 } else if (ch
== '-') {
3066 if (ch
< '0' || ch
> '9')
3067 expect("exponent digits");
3068 while (ch
>= '0' && ch
<= '9') {
3069 exp_val
= exp_val
* 10 + ch
- '0';
3072 exp_val
= exp_val
* s
;
3074 /* now we can generate the number */
3075 /* XXX: should patch directly float number */
3076 d
= (double)bn
[1] * 4294967296.0 + (double)bn
[0];
3077 d
= ldexp(d
, exp_val
- frac_bits
);
3082 /* float : should handle overflow */
3084 } else if (t
== 'L') {
3087 /* XXX: not large enough */
3088 tokc
.ld
= (long double)d
;
3094 /* decimal floats */
3096 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3101 while (ch
>= '0' && ch
<= '9') {
3102 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3108 if (ch
== 'e' || ch
== 'E') {
3109 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3113 if (ch
== '-' || ch
== '+') {
3114 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3119 if (ch
< '0' || ch
> '9')
3120 expect("exponent digits");
3121 while (ch
>= '0' && ch
<= '9') {
3122 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3134 tokc
.f
= strtof(token_buf
, NULL
);
3135 } else if (t
== 'L') {
3138 tokc
.ld
= strtold(token_buf
, NULL
);
3141 tokc
.d
= strtod(token_buf
, NULL
);
3145 unsigned long long n
, n1
;
3148 /* integer number */
3151 if (b
== 10 && *q
== '0') {
3158 /* no need for checks except for base 10 / 8 errors */
3161 } else if (t
>= 'a') {
3163 } else if (t
>= 'A') {
3168 error("invalid digit");
3172 /* detect overflow */
3173 /* XXX: this test is not reliable */
3175 error("integer constant overflow");
3178 /* XXX: not exactly ANSI compliant */
3179 if ((n
& 0xffffffff00000000LL
) != 0) {
3184 } else if (n
> 0x7fffffff) {
3195 error("three 'l's in integer constant");
3198 if (tok
== TOK_CINT
)
3200 else if (tok
== TOK_CUINT
)
3204 } else if (t
== 'U') {
3206 error("two 'u's in integer constant");
3208 if (tok
== TOK_CINT
)
3210 else if (tok
== TOK_CLLONG
)
3217 if (tok
== TOK_CINT
|| tok
== TOK_CUINT
)
3225 #define PARSE2(c1, tok1, c2, tok2) \
3236 /* return next token without macro substitution */
3237 static inline void next_nomacro1(void)
3257 /* first look if it is in fact an end of buffer */
3258 if (p
>= file
->buf_end
) {
3262 if (p
>= file
->buf_end
)
3275 TCCState
*s1
= tcc_state
;
3276 if (parse_flags
& PARSE_FLAG_LINEFEED
) {
3278 } else if (s1
->include_stack_ptr
== s1
->include_stack
||
3279 !(parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3280 /* no include left : end of file. */
3283 /* pop include file */
3285 /* test if previous '#endif' was after a #ifdef at
3287 if (tok_flags
& TOK_FLAG_ENDIF
) {
3289 printf("#endif %s\n", get_tok_str(file
->ifndef_macro_saved
, NULL
));
3291 add_cached_include(s1
, file
->inc_type
, file
->inc_filename
,
3292 file
->ifndef_macro_saved
);
3295 /* add end of include file debug info */
3297 put_stabd(N_EINCL
, 0, 0);
3299 /* pop include stack */
3301 s1
->include_stack_ptr
--;
3302 file
= *s1
->include_stack_ptr
;
3310 if (parse_flags
& PARSE_FLAG_LINEFEED
) {
3314 tok_flags
|= TOK_FLAG_BOL
;
3323 if ((tok_flags
& TOK_FLAG_BOL
) &&
3324 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3326 preprocess(tok_flags
& TOK_FLAG_BOF
);
3332 tok
= TOK_TWOSHARPS
;
3339 case 'a': case 'b': case 'c': case 'd':
3340 case 'e': case 'f': case 'g': case 'h':
3341 case 'i': case 'j': case 'k': case 'l':
3342 case 'm': case 'n': case 'o': case 'p':
3343 case 'q': case 'r': case 's': case 't':
3344 case 'u': case 'v': case 'w': case 'x':
3346 case 'A': case 'B': case 'C': case 'D':
3347 case 'E': case 'F': case 'G': case 'H':
3348 case 'I': case 'J': case 'K':
3349 case 'M': case 'N': case 'O': case 'P':
3350 case 'Q': case 'R': case 'S': case 'T':
3351 case 'U': case 'V': case 'W': case 'X':
3357 h
= TOK_HASH_FUNC(h
, c
);
3361 if (!isidnum_table
[c
])
3363 h
= TOK_HASH_FUNC(h
, c
);
3370 /* fast case : no stray found, so we have the full token
3371 and we have already hashed it */
3373 h
&= (TOK_HASH_SIZE
- 1);
3374 pts
= &hash_ident
[h
];
3379 if (ts
->len
== len
&& !memcmp(ts
->str
, p1
, len
))
3381 pts
= &(ts
->hash_next
);
3383 ts
= tok_alloc_new(pts
, p1
, len
);
3387 cstr_reset(&tokcstr
);
3390 cstr_ccat(&tokcstr
, *p1
);
3396 while (isidnum_table
[c
]) {
3397 cstr_ccat(&tokcstr
, c
);
3400 ts
= tok_alloc(tokcstr
.data
, tokcstr
.size
);
3406 if (t
!= '\\' && t
!= '\'' && t
!= '\"') {
3408 goto parse_ident_fast
;
3411 if (c
== '\'' || c
== '\"') {
3415 cstr_reset(&tokcstr
);
3416 cstr_ccat(&tokcstr
, 'L');
3417 goto parse_ident_slow
;
3421 case '0': case '1': case '2': case '3':
3422 case '4': case '5': case '6': case '7':
3425 cstr_reset(&tokcstr
);
3426 /* after the first digit, accept digits, alpha, '.' or sign if
3427 prefixed by 'eEpP' */
3431 cstr_ccat(&tokcstr
, c
);
3433 if (!(isnum(c
) || isid(c
) || c
== '.' ||
3434 ((c
== '+' || c
== '-') &&
3435 (t
== 'e' || t
== 'E' || t
== 'p' || t
== 'P'))))
3438 /* We add a trailing '\0' to ease parsing */
3439 cstr_ccat(&tokcstr
, '\0');
3440 tokc
.cstr
= &tokcstr
;
3444 /* special dot handling because it can also start a number */
3447 cstr_reset(&tokcstr
);
3448 cstr_ccat(&tokcstr
, '.');
3450 } else if (c
== '.') {
3470 /* parse the string */
3472 p
= parse_pp_string(p
, sep
, &str
);
3473 cstr_ccat(&str
, '\0');
3475 /* eval the escape (should be done as TOK_PPNUM) */
3476 cstr_reset(&tokcstr
);
3477 parse_escape_string(&tokcstr
, str
.data
, is_long
);
3482 /* XXX: make it portable */
3486 char_size
= sizeof(int);
3487 if (tokcstr
.size
<= char_size
)
3488 error("empty character constant");
3489 if (tokcstr
.size
> 2 * char_size
)
3490 warning("multi-character character constant");
3492 tokc
.i
= *(int8_t *)tokcstr
.data
;
3495 tokc
.i
= *(int *)tokcstr
.data
;
3499 tokc
.cstr
= &tokcstr
;
3513 } else if (c
== '<') {
3531 } else if (c
== '>') {
3549 } else if (c
== '=') {
3562 } else if (c
== '=') {
3575 } else if (c
== '=') {
3588 } else if (c
== '=') {
3591 } else if (c
== '>') {
3599 PARSE2('!', '!', '=', TOK_NE
)
3600 PARSE2('=', '=', '=', TOK_EQ
)
3601 PARSE2('*', '*', '=', TOK_A_MUL
)
3602 PARSE2('%', '%', '=', TOK_A_MOD
)
3603 PARSE2('^', '^', '=', TOK_A_XOR
)
3605 /* comments or operator */
3609 p
= parse_comment(p
);
3611 } else if (c
== '/') {
3612 p
= parse_line_comment(p
);
3614 } else if (c
== '=') {
3634 case '$': /* only used in assembler */
3639 error("unrecognized character \\x%02x", c
);
3644 #if defined(PARSE_DEBUG)
3645 printf("token = %s\n", get_tok_str(tok
, &tokc
));
3649 /* return next token without macro substitution. Can read input from
3651 static void next_nomacro(void)
3657 TOK_GET(tok
, macro_ptr
, tokc
);
3658 if (tok
== TOK_LINENUM
) {
3659 file
->line_num
= tokc
.i
;
3668 /* substitute args in macro_str and return allocated string */
3669 static int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
3671 int *st
, last_tok
, t
, notfirst
;
3680 TOK_GET(t
, macro_str
, cval
);
3685 TOK_GET(t
, macro_str
, cval
);
3688 s
= sym_find2(args
, t
);
3695 cstr_ccat(&cstr
, ' ');
3696 TOK_GET(t
, st
, cval
);
3697 cstr_cat(&cstr
, get_tok_str(t
, &cval
));
3700 cstr_ccat(&cstr
, '\0');
3702 printf("stringize: %s\n", (char *)cstr
.data
);
3706 tok_str_add2(&str
, TOK_STR
, &cval
);
3709 tok_str_add2(&str
, t
, &cval
);
3711 } else if (t
>= TOK_IDENT
) {
3712 s
= sym_find2(args
, t
);
3715 /* if '##' is present before or after, no arg substitution */
3716 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
3717 /* special case for var arg macros : ## eats the
3718 ',' if empty VA_ARGS variable. */
3719 /* XXX: test of the ',' is not 100%
3720 reliable. should fix it to avoid security
3722 if (gnu_ext
&& s
->type
.t
&&
3723 last_tok
== TOK_TWOSHARPS
&&
3724 str
.len
>= 2 && str
.str
[str
.len
- 2] == ',') {
3726 /* suppress ',' '##' */
3729 /* suppress '##' and add variable */
3737 TOK_GET(t1
, st
, cval
);
3740 tok_str_add2(&str
, t1
, &cval
);
3744 /* NOTE: the stream cannot be read when macro
3745 substituing an argument */
3746 macro_subst(&str
, nested_list
, st
, 0);
3749 tok_str_add(&str
, t
);
3752 tok_str_add2(&str
, t
, &cval
);
3756 tok_str_add(&str
, 0);
3760 static char const ab_month_name
[12][4] =
3762 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
3763 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
3766 /* do macro substitution of current token with macro 's' and add
3767 result to (tok_str,tok_len). 'nested_list' is the list of all
3768 macros we got inside to avoid recursing. Return non zero if no
3769 substitution needs to be done */
3770 static int macro_subst_tok(TokenString
*tok_str
,
3771 Sym
**nested_list
, Sym
*s
, int can_read_stream
)
3773 Sym
*args
, *sa
, *sa1
;
3774 int mstr_allocated
, parlevel
, *mstr
, t
;
3780 /* if symbol is a macro, prepare substitution */
3782 /* special macros */
3783 if (tok
== TOK___LINE__
) {
3784 cval
.i
= file
->line_num
;
3785 tok_str_add2(tok_str
, TOK_CINT
, &cval
);
3786 } else if (tok
== TOK___FILE__
) {
3787 cstrval
= file
->filename
;
3789 tok_str_add2(tok_str
, TOK_STR
, &cval
);
3790 } else if (tok
== TOK___DATE__
|| tok
== TOK___TIME__
) {
3796 tm
= localtime(&ti
);
3797 if (tok
== TOK___DATE__
) {
3798 snprintf(buf
, sizeof(buf
), "%s %2d %d",
3799 ab_month_name
[tm
->tm_mon
], tm
->tm_mday
, tm
->tm_year
+ 1900);
3801 snprintf(buf
, sizeof(buf
), "%02d:%02d:%02d",
3802 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
);
3807 cstr_cat(&cstr
, cstrval
);
3808 cstr_ccat(&cstr
, '\0');
3810 tok_str_add2(tok_str
, TOK_STR
, &cval
);
3815 if (s
->type
.t
== MACRO_FUNC
) {
3816 /* NOTE: we do not use next_nomacro to avoid eating the
3817 next token. XXX: find better solution */
3820 if (t
== 0 && can_read_stream
) {
3821 /* end of macro stream: we must look at the token
3822 after in the file */
3828 /* XXX: incorrect with comments */
3829 ch
= file
->buf_ptr
[0];
3830 while (is_space(ch
) || ch
== '\n')
3834 if (t
!= '(') /* no macro subst */
3837 /* argument macro */
3842 /* NOTE: empty args are allowed, except if no args */
3844 /* handle '()' case */
3845 if (!args
&& !sa
&& tok
== ')')
3848 error("macro '%s' used with too many args",
3849 get_tok_str(s
->v
, 0));
3852 /* NOTE: non zero sa->t indicates VA_ARGS */
3853 while ((parlevel
> 0 ||
3855 (tok
!= ',' || sa
->type
.t
))) &&
3859 else if (tok
== ')')
3861 tok_str_add2(&str
, tok
, &tokc
);
3864 tok_str_add(&str
, 0);
3865 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, sa
->type
.t
, (int)str
.str
);
3868 /* special case for gcc var args: add an empty
3869 var arg argument if it is omitted */
3870 if (sa
&& sa
->type
.t
&& gnu_ext
)
3880 error("macro '%s' used with too few args",
3881 get_tok_str(s
->v
, 0));
3884 /* now subst each arg */
3885 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
3890 tok_str_free((int *)sa
->c
);
3896 sym_push2(nested_list
, s
->v
, 0, 0);
3897 macro_subst(tok_str
, nested_list
, mstr
, 1);
3898 /* pop nested defined symbol */
3900 *nested_list
= sa1
->prev
;
3908 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
3909 return the resulting string (which must be freed). */
3910 static inline int *macro_twosharps(const int *macro_str
)
3913 const int *macro_ptr1
, *start_macro_ptr
, *ptr
, *saved_macro_ptr
;
3915 const char *p1
, *p2
;
3917 TokenString macro_str1
;
3920 start_macro_ptr
= macro_str
;
3921 /* we search the first '##' */
3923 macro_ptr1
= macro_str
;
3924 TOK_GET(t
, macro_str
, cval
);
3925 /* nothing more to do if end of string */
3928 if (*macro_str
== TOK_TWOSHARPS
)
3932 /* we saw '##', so we need more processing to handle it */
3934 tok_str_new(¯o_str1
);
3938 /* add all tokens seen so far */
3939 for(ptr
= start_macro_ptr
; ptr
< macro_ptr1
;) {
3940 TOK_GET(t
, ptr
, cval
);
3941 tok_str_add2(¯o_str1
, t
, &cval
);
3943 saved_macro_ptr
= macro_ptr
;
3944 /* XXX: get rid of the use of macro_ptr here */
3945 macro_ptr
= (int *)macro_str
;
3947 while (*macro_ptr
== TOK_TWOSHARPS
) {
3949 macro_ptr1
= macro_ptr
;
3952 TOK_GET(t
, macro_ptr
, cval
);
3953 /* We concatenate the two tokens if we have an
3954 identifier or a preprocessing number */
3956 p1
= get_tok_str(tok
, &tokc
);
3957 cstr_cat(&cstr
, p1
);
3958 p2
= get_tok_str(t
, &cval
);
3959 cstr_cat(&cstr
, p2
);
3960 cstr_ccat(&cstr
, '\0');
3962 if ((tok
>= TOK_IDENT
|| tok
== TOK_PPNUM
) &&
3963 (t
>= TOK_IDENT
|| t
== TOK_PPNUM
)) {
3964 if (tok
== TOK_PPNUM
) {
3965 /* if number, then create a number token */
3966 /* NOTE: no need to allocate because
3967 tok_str_add2() does it */
3970 /* if identifier, we must do a test to
3971 validate we have a correct identifier */
3972 if (t
== TOK_PPNUM
) {
3982 if (!isnum(c
) && !isid(c
))
3986 ts
= tok_alloc(cstr
.data
, strlen(cstr
.data
));
3987 tok
= ts
->tok
; /* modify current token */
3990 const char *str
= cstr
.data
;
3991 const unsigned char *q
;
3993 /* we look for a valid token */
3994 /* XXX: do more extensive checks */
3995 if (!strcmp(str
, ">>=")) {
3997 } else if (!strcmp(str
, "<<=")) {
3999 } else if (strlen(str
) == 2) {
4000 /* search in two bytes table */
4005 if (q
[0] == str
[0] && q
[1] == str
[1])
4012 /* NOTE: because get_tok_str use a static buffer,
4015 p1
= get_tok_str(tok
, &tokc
);
4016 cstr_cat(&cstr
, p1
);
4017 cstr_ccat(&cstr
, '\0');
4018 p2
= get_tok_str(t
, &cval
);
4019 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr
.data
, p2
);
4020 /* cannot merge tokens: just add them separately */
4021 tok_str_add2(¯o_str1
, tok
, &tokc
);
4022 /* XXX: free associated memory ? */
4029 tok_str_add2(¯o_str1
, tok
, &tokc
);
4034 macro_ptr
= (int *)saved_macro_ptr
;
4036 tok_str_add(¯o_str1
, 0);
4037 return macro_str1
.str
;
4041 /* do macro substitution of macro_str and add result to
4042 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4043 inside to avoid recursing. */
4044 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
4045 const int *macro_str
, int can_read_stream
)
4048 int *saved_macro_ptr
, *macro_str1
;
4053 /* first scan for '##' operator handling */
4055 macro_str1
= macro_twosharps(ptr
);
4059 /* NOTE: ptr == NULL can only happen if tokens are read from
4060 file stream due to a macro function call */
4063 TOK_GET(t
, ptr
, cval
);
4068 /* if nested substitution, do nothing */
4069 if (sym_find2(*nested_list
, t
))
4071 saved_macro_ptr
= macro_ptr
;
4072 macro_ptr
= (int *)ptr
;
4074 ret
= macro_subst_tok(tok_str
, nested_list
, s
, can_read_stream
);
4075 ptr
= (int *)macro_ptr
;
4076 macro_ptr
= saved_macro_ptr
;
4081 tok_str_add2(tok_str
, t
, &cval
);
4085 tok_str_free(macro_str1
);
4088 /* return next token with macro substitution */
4089 static void next(void)
4091 Sym
*nested_list
, *s
;
4097 /* if not reading from macro substituted string, then try
4098 to substitute macros */
4099 if (tok
>= TOK_IDENT
&&
4100 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
4101 s
= define_find(tok
);
4103 /* we have a macro: we try to substitute */
4106 if (macro_subst_tok(&str
, &nested_list
, s
, 1) == 0) {
4107 /* substitution done, NOTE: maybe empty */
4108 tok_str_add(&str
, 0);
4109 macro_ptr
= str
.str
;
4110 macro_ptr_allocated
= str
.str
;
4117 /* end of macro or end of unget buffer */
4118 if (unget_buffer_enabled
) {
4119 macro_ptr
= unget_saved_macro_ptr
;
4120 unget_buffer_enabled
= 0;
4122 /* end of macro string: free it */
4123 tok_str_free(macro_ptr_allocated
);
4130 /* convert preprocessor tokens into C tokens */
4131 if (tok
== TOK_PPNUM
&&
4132 (parse_flags
& PARSE_FLAG_TOK_NUM
)) {
4133 parse_number((char *)tokc
.cstr
->data
);
4137 /* push back current token and set current token to 'last_tok'. Only
4138 identifier case handled for labels. */
4139 static inline void unget_tok(int last_tok
)
4143 unget_saved_macro_ptr
= macro_ptr
;
4144 unget_buffer_enabled
= 1;
4145 q
= unget_saved_buffer
;
4148 n
= tok_ext_size(tok
) - 1;
4151 *q
= 0; /* end of token string */
4156 void swap(int *p
, int *q
)
4164 void vsetc(CType
*type
, int r
, CValue
*vc
)
4168 if (vtop
>= vstack
+ VSTACK_SIZE
)
4169 error("memory full");
4170 /* cannot let cpu flags if other instruction are generated. Also
4171 avoid leaving VT_JMP anywhere except on the top of the stack
4172 because it would complicate the code generator. */
4173 if (vtop
>= vstack
) {
4174 v
= vtop
->r
& VT_VALMASK
;
4175 if (v
== VT_CMP
|| (v
& ~1) == VT_JMP
)
4181 vtop
->r2
= VT_CONST
;
4185 /* push integer constant */
4190 vsetc(&int_type
, VT_CONST
, &cval
);
4193 /* Return a static symbol pointing to a section */
4194 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
4195 unsigned long offset
, unsigned long size
)
4201 sym
= global_identifier_push(v
, type
->t
| VT_STATIC
, 0);
4202 sym
->type
.ref
= type
->ref
;
4203 sym
->r
= VT_CONST
| VT_SYM
;
4204 put_extern_sym(sym
, sec
, offset
, size
);
4208 /* push a reference to a section offset by adding a dummy symbol */
4209 static void vpush_ref(CType
*type
, Section
*sec
, unsigned long offset
, unsigned long size
)
4214 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4215 vtop
->sym
= get_sym_ref(type
, sec
, offset
, size
);
4218 /* define a new external reference to a symbol 'v' of type 'u' */
4219 static Sym
*external_global_sym(int v
, CType
*type
, int r
)
4225 /* push forward reference */
4226 s
= global_identifier_push(v
, type
->t
| VT_EXTERN
, 0);
4227 s
->type
.ref
= type
->ref
;
4228 s
->r
= r
| VT_CONST
| VT_SYM
;
4233 /* define a new external reference to a symbol 'v' of type 'u' */
4234 static Sym
*external_sym(int v
, CType
*type
, int r
)
4240 /* push forward reference */
4241 s
= sym_push(v
, type
, r
| VT_CONST
| VT_SYM
, 0);
4242 s
->type
.t
|= VT_EXTERN
;
4244 if (!is_compatible_types(&s
->type
, type
))
4245 error("incompatible types for redefinition of '%s'",
4246 get_tok_str(v
, NULL
));
4251 /* push a reference to global symbol v */
4252 static void vpush_global_sym(CType
*type
, int v
)
4257 sym
= external_global_sym(v
, type
, 0);
4259 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4263 void vset(CType
*type
, int r
, int v
)
4268 vsetc(type
, r
, &cval
);
4271 void vseti(int r
, int v
)
4287 void vpushv(SValue
*v
)
4289 if (vtop
>= vstack
+ VSTACK_SIZE
)
4290 error("memory full");
4300 /* save r to the memory stack, and mark it as being free */
4301 void save_reg(int r
)
4303 int l
, saved
, size
, align
;
4307 /* modify all stack values */
4310 for(p
=vstack
;p
<=vtop
;p
++) {
4311 if ((p
->r
& VT_VALMASK
) == r
||
4312 (p
->r2
& VT_VALMASK
) == r
) {
4313 /* must save value on stack if not already done */
4315 /* NOTE: must reload 'r' because r might be equal to r2 */
4316 r
= p
->r
& VT_VALMASK
;
4317 /* store register in the stack */
4319 if ((p
->r
& VT_LVAL
) ||
4320 (!is_float(type
->t
) && (type
->t
& VT_BTYPE
) != VT_LLONG
))
4322 size
= type_size(type
, &align
);
4323 loc
= (loc
- size
) & -align
;
4324 sv
.type
.t
= type
->t
;
4325 sv
.r
= VT_LOCAL
| VT_LVAL
;
4328 #ifdef TCC_TARGET_I386
4329 /* x86 specific: need to pop fp register ST0 if saved */
4330 if (r
== TREG_ST0
) {
4331 o(0xd9dd); /* fstp %st(1) */
4334 /* special long long case */
4335 if ((type
->t
& VT_BTYPE
) == VT_LLONG
) {
4342 /* mark that stack entry as being saved on the stack */
4343 if (p
->r
& VT_LVAL
) {
4344 /* also clear the bounded flag because the
4345 relocation address of the function was stored in
4347 p
->r
= (p
->r
& ~(VT_VALMASK
| VT_BOUNDED
)) | VT_LLOCAL
;
4349 p
->r
= lvalue_type(p
->type
.t
) | VT_LOCAL
;
4357 /* find a register of class 'rc2' with at most one reference on stack.
4358 * If none, call get_reg(rc) */
4359 int get_reg_ex(int rc
, int rc2
)
4364 for(r
=0;r
<NB_REGS
;r
++) {
4365 if (reg_classes
[r
] & rc2
) {
4368 for(p
= vstack
; p
<= vtop
; p
++) {
4369 if ((p
->r
& VT_VALMASK
) == r
||
4370 (p
->r2
& VT_VALMASK
) == r
)
4380 /* find a free register of class 'rc'. If none, save one register */
4386 /* find a free register */
4387 for(r
=0;r
<NB_REGS
;r
++) {
4388 if (reg_classes
[r
] & rc
) {
4389 for(p
=vstack
;p
<=vtop
;p
++) {
4390 if ((p
->r
& VT_VALMASK
) == r
||
4391 (p
->r2
& VT_VALMASK
) == r
)
4399 /* no register left : free the first one on the stack (VERY
4400 IMPORTANT to start from the bottom to ensure that we don't
4401 spill registers used in gen_opi()) */
4402 for(p
=vstack
;p
<=vtop
;p
++) {
4403 r
= p
->r
& VT_VALMASK
;
4404 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
))
4406 /* also look at second register (if long long) */
4407 r
= p
->r2
& VT_VALMASK
;
4408 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
4414 /* Should never comes here */
4418 /* save registers up to (vtop - n) stack entry */
4419 void save_regs(int n
)
4424 for(p
= vstack
;p
<= p1
; p
++) {
4425 r
= p
->r
& VT_VALMASK
;
4432 /* move register 's' to 'r', and flush previous value of r to memory
4434 void move_reg(int r
, int s
)
4447 /* get address of vtop (vtop MUST BE an lvalue) */
4450 vtop
->r
&= ~VT_LVAL
;
4451 /* tricky: if saved lvalue, then we can go back to lvalue */
4452 if ((vtop
->r
& VT_VALMASK
) == VT_LLOCAL
)
4453 vtop
->r
= (vtop
->r
& ~(VT_VALMASK
| VT_LVAL_TYPE
)) | VT_LOCAL
| VT_LVAL
;
4456 #ifdef CONFIG_TCC_BCHECK
4457 /* generate lvalue bound code */
4463 vtop
->r
&= ~VT_MUSTBOUND
;
4464 /* if lvalue, then use checking code before dereferencing */
4465 if (vtop
->r
& VT_LVAL
) {
4466 /* if not VT_BOUNDED value, then make one */
4467 if (!(vtop
->r
& VT_BOUNDED
)) {
4468 lval_type
= vtop
->r
& (VT_LVAL_TYPE
| VT_LVAL
);
4469 /* must save type because we must set it to int to get pointer */
4471 vtop
->type
.t
= VT_INT
;
4474 gen_bounded_ptr_add();
4475 vtop
->r
|= lval_type
;
4478 /* then check for dereferencing */
4479 gen_bounded_ptr_deref();
4484 /* store vtop a register belonging to class 'rc'. lvalues are
4485 converted to values. Cannot be used if cannot be converted to
4486 register value (such as structures). */
4489 int r
, r2
, rc2
, bit_pos
, bit_size
, size
, align
, i
;
4490 unsigned long long ll
;
4492 /* NOTE: get_reg can modify vstack[] */
4493 if (vtop
->type
.t
& VT_BITFIELD
) {
4494 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
4495 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
4496 /* remove bit field info to avoid loops */
4497 vtop
->type
.t
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
4498 /* generate shifts */
4499 vpushi(32 - (bit_pos
+ bit_size
));
4501 vpushi(32 - bit_size
);
4502 /* NOTE: transformed to SHR if unsigned */
4506 if (is_float(vtop
->type
.t
) &&
4507 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4510 unsigned long offset
;
4512 /* XXX: unify with initializers handling ? */
4513 /* CPUs usually cannot use float constants, so we store them
4514 generically in data segment */
4515 size
= type_size(&vtop
->type
, &align
);
4516 offset
= (data_section
->data_offset
+ align
- 1) & -align
;
4517 data_section
->data_offset
= offset
;
4518 /* XXX: not portable yet */
4519 ptr
= section_ptr_add(data_section
, size
);
4522 ptr
[i
] = vtop
->c
.tab
[i
];
4523 sym
= get_sym_ref(&vtop
->type
, data_section
, offset
, size
<< 2);
4524 vtop
->r
|= VT_LVAL
| VT_SYM
;
4528 #ifdef CONFIG_TCC_BCHECK
4529 if (vtop
->r
& VT_MUSTBOUND
)
4533 r
= vtop
->r
& VT_VALMASK
;
4534 /* need to reload if:
4536 - lvalue (need to dereference pointer)
4537 - already a register, but not in the right class */
4538 if (r
>= VT_CONST
||
4539 (vtop
->r
& VT_LVAL
) ||
4540 !(reg_classes
[r
] & rc
) ||
4541 ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
&&
4542 !(reg_classes
[vtop
->r2
] & rc
))) {
4544 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
4545 /* two register type load : expand to two words
4547 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4550 vtop
->c
.ui
= ll
; /* first word */
4552 vtop
->r
= r
; /* save register value */
4553 vpushi(ll
>> 32); /* second word */
4554 } else if (r
>= VT_CONST
||
4555 (vtop
->r
& VT_LVAL
)) {
4556 /* load from memory */
4559 vtop
[-1].r
= r
; /* save register value */
4560 /* increment pointer to get second word */
4561 vtop
->type
.t
= VT_INT
;
4567 /* move registers */
4570 vtop
[-1].r
= r
; /* save register value */
4571 vtop
->r
= vtop
[-1].r2
;
4573 /* allocate second register */
4580 /* write second register */
4582 } else if ((vtop
->r
& VT_LVAL
) && !is_float(vtop
->type
.t
)) {
4584 /* lvalue of scalar type : need to use lvalue type
4585 because of possible cast */
4588 /* compute memory access type */
4589 if (vtop
->r
& VT_LVAL_BYTE
)
4591 else if (vtop
->r
& VT_LVAL_SHORT
)
4593 if (vtop
->r
& VT_LVAL_UNSIGNED
)
4597 /* restore wanted type */
4600 /* one register type load */
4609 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4610 void gv2(int rc1
, int rc2
)
4614 /* generate more generic register first. But VT_JMP or VT_CMP
4615 values must be generated first in all cases to avoid possible
4617 v
= vtop
[0].r
& VT_VALMASK
;
4618 if (v
!= VT_CMP
&& (v
& ~1) != VT_JMP
&& rc1
<= rc2
) {
4623 /* test if reload is needed for first register */
4624 if ((vtop
[-1].r
& VT_VALMASK
) >= VT_CONST
) {
4634 /* test if reload is needed for first register */
4635 if ((vtop
[0].r
& VT_VALMASK
) >= VT_CONST
) {
4641 /* expand long long on stack in two int registers */
4646 u
= vtop
->type
.t
& VT_UNSIGNED
;
4649 vtop
[0].r
= vtop
[-1].r2
;
4650 vtop
[0].r2
= VT_CONST
;
4651 vtop
[-1].r2
= VT_CONST
;
4652 vtop
[0].type
.t
= VT_INT
| u
;
4653 vtop
[-1].type
.t
= VT_INT
| u
;
4656 /* build a long long from two ints */
4659 gv2(RC_INT
, RC_INT
);
4660 vtop
[-1].r2
= vtop
[0].r
;
4661 vtop
[-1].type
.t
= t
;
4665 /* rotate n first stack elements to the bottom
4666 I1 ... In -> I2 ... In I1 [top is right]
4674 for(i
=-n
+1;i
!=0;i
++)
4675 vtop
[i
] = vtop
[i
+1];
4679 /* rotate n first stack elements to the top
4680 I1 ... In -> In I1 ... I(n-1) [top is right]
4688 for(i
= 0;i
< n
- 1; i
++)
4689 vtop
[-i
] = vtop
[-i
- 1];
4693 /* pop stack value */
4697 v
= vtop
->r
& VT_VALMASK
;
4698 #ifdef TCC_TARGET_I386
4699 /* for x86, we need to pop the FP stack */
4700 if (v
== TREG_ST0
&& !nocode_wanted
) {
4701 o(0xd9dd); /* fstp %st(1) */
4704 if (v
== VT_JMP
|| v
== VT_JMPI
) {
4705 /* need to put correct jump if && or || without test */
4711 /* convert stack entry to register and duplicate its value in another
4719 if ((t
& VT_BTYPE
) == VT_LLONG
) {
4726 /* stack: H L L1 H1 */
4734 /* duplicate value */
4745 load(r1
, &sv
); /* move r to r1 */
4747 /* duplicates value */
4752 /* generate CPU independent (unsigned) long long operations */
4753 void gen_opl(int op
)
4755 int t
, a
, b
, op1
, c
, i
;
4762 func
= TOK___divdi3
;
4765 func
= TOK___udivdi3
;
4768 func
= TOK___moddi3
;
4771 func
= TOK___umoddi3
;
4773 /* call generic long long function */
4774 vpush_global_sym(&func_old_type
, func
);
4779 vtop
->r2
= REG_LRET
;
4792 /* stack: L1 H1 L2 H2 */
4797 vtop
[-2] = vtop
[-3];
4800 /* stack: H1 H2 L1 L2 */
4806 /* stack: H1 H2 L1 L2 ML MH */
4809 /* stack: ML MH H1 H2 L1 L2 */
4813 /* stack: ML MH H1 L2 H2 L1 */
4818 /* stack: ML MH M1 M2 */
4821 } else if (op
== '+' || op
== '-') {
4822 /* XXX: add non carry method too (for MIPS or alpha) */
4828 /* stack: H1 H2 (L1 op L2) */
4831 gen_op(op1
+ 1); /* TOK_xxxC2 */
4834 /* stack: H1 H2 (L1 op L2) */
4837 /* stack: (L1 op L2) H1 H2 */
4839 /* stack: (L1 op L2) (H1 op H2) */
4847 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
4848 t
= vtop
[-1].type
.t
;
4852 /* stack: L H shift */
4854 /* constant: simpler */
4855 /* NOTE: all comments are for SHL. the other cases are
4856 done by swaping words */
4867 if (op
!= TOK_SAR
) {
4900 /* XXX: should provide a faster fallback on x86 ? */
4903 func
= TOK___sardi3
;
4906 func
= TOK___shrdi3
;
4909 func
= TOK___shldi3
;
4915 /* compare operations */
4921 /* stack: L1 H1 L2 H2 */
4923 vtop
[-1] = vtop
[-2];
4925 /* stack: L1 L2 H1 H2 */
4928 /* when values are equal, we need to compare low words. since
4929 the jump is inverted, we invert the test too. */
4932 else if (op1
== TOK_GT
)
4934 else if (op1
== TOK_ULT
)
4936 else if (op1
== TOK_UGT
)
4941 if (op1
!= TOK_NE
) {
4945 /* generate non equal test */
4946 /* XXX: NOT PORTABLE yet */
4950 #if defined(TCC_TARGET_I386)
4951 b
= psym(0x850f, 0);
4952 #elif defined(TCC_TARGET_ARM)
4954 o(0x1A000000 | encbranch(ind
, 0, 1));
4956 #error not supported
4960 /* compare low. Always unsigned */
4964 else if (op1
== TOK_LE
)
4966 else if (op1
== TOK_GT
)
4968 else if (op1
== TOK_GE
)
4978 /* handle integer constant optimizations and various machine
4980 void gen_opic(int op
)
4987 /* currently, we cannot do computations with forward symbols */
4988 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
4989 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
4993 case '+': v1
->c
.i
+= fc
; break;
4994 case '-': v1
->c
.i
-= fc
; break;
4995 case '&': v1
->c
.i
&= fc
; break;
4996 case '^': v1
->c
.i
^= fc
; break;
4997 case '|': v1
->c
.i
|= fc
; break;
4998 case '*': v1
->c
.i
*= fc
; break;
5005 /* if division by zero, generate explicit division */
5008 error("division by zero in constant");
5012 default: v1
->c
.i
/= fc
; break;
5013 case '%': v1
->c
.i
%= fc
; break;
5014 case TOK_UDIV
: v1
->c
.i
= (unsigned)v1
->c
.i
/ fc
; break;
5015 case TOK_UMOD
: v1
->c
.i
= (unsigned)v1
->c
.i
% fc
; break;
5018 case TOK_SHL
: v1
->c
.i
<<= fc
; break;
5019 case TOK_SHR
: v1
->c
.i
= (unsigned)v1
->c
.i
>> fc
; break;
5020 case TOK_SAR
: v1
->c
.i
>>= fc
; break;
5022 case TOK_ULT
: v1
->c
.i
= (unsigned)v1
->c
.i
< (unsigned)fc
; break;
5023 case TOK_UGE
: v1
->c
.i
= (unsigned)v1
->c
.i
>= (unsigned)fc
; break;
5024 case TOK_EQ
: v1
->c
.i
= v1
->c
.i
== fc
; break;
5025 case TOK_NE
: v1
->c
.i
= v1
->c
.i
!= fc
; break;
5026 case TOK_ULE
: v1
->c
.i
= (unsigned)v1
->c
.i
<= (unsigned)fc
; break;
5027 case TOK_UGT
: v1
->c
.i
= (unsigned)v1
->c
.i
> (unsigned)fc
; break;
5028 case TOK_LT
: v1
->c
.i
= v1
->c
.i
< fc
; break;
5029 case TOK_GE
: v1
->c
.i
= v1
->c
.i
>= fc
; break;
5030 case TOK_LE
: v1
->c
.i
= v1
->c
.i
<= fc
; break;
5031 case TOK_GT
: v1
->c
.i
= v1
->c
.i
> fc
; break;
5033 case TOK_LAND
: v1
->c
.i
= v1
->c
.i
&& fc
; break;
5034 case TOK_LOR
: v1
->c
.i
= v1
->c
.i
|| fc
; break;
5040 /* if commutative ops, put c2 as constant */
5041 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
5042 op
== '|' || op
== '*')) {
5047 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
5050 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
5051 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
5057 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
5058 /* try to use shifts instead of muls or divs */
5059 if (fc
> 0 && (fc
& (fc
- 1)) == 0) {
5068 else if (op
== TOK_PDIV
)
5074 } else if (c2
&& (op
== '+' || op
== '-') &&
5075 (vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) ==
5076 (VT_CONST
| VT_SYM
)) {
5077 /* symbol + constant case */
5084 if (!nocode_wanted
) {
5085 /* call low level op generator */
5094 /* generate a floating point operation with constant propagation */
5095 void gen_opif(int op
)
5103 /* currently, we cannot do computations with forward symbols */
5104 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5105 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5107 if (v1
->type
.t
== VT_FLOAT
) {
5110 } else if (v1
->type
.t
== VT_DOUBLE
) {
5118 /* NOTE: we only do constant propagation if finite number (not
5119 NaN or infinity) (ANSI spec) */
5120 if (!ieee_finite(f1
) || !ieee_finite(f2
))
5124 case '+': f1
+= f2
; break;
5125 case '-': f1
-= f2
; break;
5126 case '*': f1
*= f2
; break;
5130 error("division by zero in constant");
5135 /* XXX: also handles tests ? */
5139 /* XXX: overflow test ? */
5140 if (v1
->type
.t
== VT_FLOAT
) {
5142 } else if (v1
->type
.t
== VT_DOUBLE
) {
5150 if (!nocode_wanted
) {
5158 static int pointed_size(CType
*type
)
5161 return type_size(pointed_type(type
), &align
);
5164 static inline int is_null_pointer(SValue
*p
)
5166 if ((p
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
5168 return ((p
->type
.t
& VT_BTYPE
) == VT_INT
&& p
->c
.i
== 0) ||
5169 ((p
->type
.t
& VT_BTYPE
) == VT_LLONG
&& p
->c
.ll
== 0);
5172 static inline int is_integer_btype(int bt
)
5174 return (bt
== VT_BYTE
|| bt
== VT_SHORT
||
5175 bt
== VT_INT
|| bt
== VT_LLONG
);
5178 /* check types for comparison or substraction of pointers */
5179 static void check_comparison_pointer_types(SValue
*p1
, SValue
*p2
, int op
)
5181 CType
*type1
, *type2
, tmp_type1
, tmp_type2
;
5184 /* null pointers are accepted for all comparisons as gcc */
5185 if (is_null_pointer(p1
) || is_null_pointer(p2
))
5189 bt1
= type1
->t
& VT_BTYPE
;
5190 bt2
= type2
->t
& VT_BTYPE
;
5191 /* accept comparison between pointer and integer with a warning */
5192 if ((is_integer_btype(bt1
) || is_integer_btype(bt2
)) && op
!= '-') {
5193 warning("comparison between pointer and integer");
5197 /* both must be pointers or implicit function pointers */
5198 if (bt1
== VT_PTR
) {
5199 type1
= pointed_type(type1
);
5200 } else if (bt1
!= VT_FUNC
)
5201 goto invalid_operands
;
5203 if (bt2
== VT_PTR
) {
5204 type2
= pointed_type(type2
);
5205 } else if (bt2
!= VT_FUNC
) {
5207 error("invalid operands to binary %s", get_tok_str(op
, NULL
));
5209 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
5210 (type2
->t
& VT_BTYPE
) == VT_VOID
)
5214 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5215 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5216 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
5217 /* gcc-like error if '-' is used */
5219 goto invalid_operands
;
5221 warning("comparison of distinct pointer types lacks a cast");
5225 /* generic gen_op: handles types problems */
5228 int u
, t1
, t2
, bt1
, bt2
, t
;
5231 t1
= vtop
[-1].type
.t
;
5232 t2
= vtop
[0].type
.t
;
5233 bt1
= t1
& VT_BTYPE
;
5234 bt2
= t2
& VT_BTYPE
;
5236 if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
5237 /* at least one operand is a pointer */
5238 /* relationnal op: must be both pointers */
5239 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
5240 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5241 /* pointers are handled are unsigned */
5242 t
= VT_INT
| VT_UNSIGNED
;
5245 /* if both pointers, then it must be the '-' op */
5246 if (bt1
== VT_PTR
&& bt2
== VT_PTR
) {
5248 error("cannot use pointers here");
5249 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5250 /* XXX: check that types are compatible */
5251 u
= pointed_size(&vtop
[-1].type
);
5253 /* set to integer type */
5254 vtop
->type
.t
= VT_INT
;
5258 /* exactly one pointer : must be '+' or '-'. */
5259 if (op
!= '-' && op
!= '+')
5260 error("cannot use pointers here");
5261 /* Put pointer as first operand */
5262 if (bt2
== VT_PTR
) {
5266 type1
= vtop
[-1].type
;
5267 /* XXX: cast to int ? (long long case) */
5268 vpushi(pointed_size(&vtop
[-1].type
));
5270 #ifdef CONFIG_TCC_BCHECK
5271 /* if evaluating constant expression, no code should be
5272 generated, so no bound check */
5273 if (do_bounds_check
&& !const_wanted
) {
5274 /* if bounded pointers, we generate a special code to
5281 gen_bounded_ptr_add();
5287 /* put again type if gen_opic() swaped operands */
5290 } else if (is_float(bt1
) || is_float(bt2
)) {
5291 /* compute bigger type and do implicit casts */
5292 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
5294 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
5299 /* floats can only be used for a few operations */
5300 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
5301 (op
< TOK_ULT
|| op
> TOK_GT
))
5302 error("invalid operands for binary operation");
5304 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
5305 /* cast to biggest op */
5307 /* convert to unsigned if it does not fit in a long long */
5308 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
5309 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
5313 /* integer operations */
5315 /* convert to unsigned if it does not fit in an integer */
5316 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
5317 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
5320 /* XXX: currently, some unsigned operations are explicit, so
5321 we modify them here */
5322 if (t
& VT_UNSIGNED
) {
5329 else if (op
== TOK_LT
)
5331 else if (op
== TOK_GT
)
5333 else if (op
== TOK_LE
)
5335 else if (op
== TOK_GE
)
5342 /* special case for shifts and long long: we keep the shift as
5344 if (op
== TOK_SHR
|| op
== TOK_SAR
|| op
== TOK_SHL
)
5349 else if ((t
& VT_BTYPE
) == VT_LLONG
)
5353 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
5354 /* relationnal op: the result is an int */
5355 vtop
->type
.t
= VT_INT
;
5362 /* generic itof for unsigned long long case */
5363 void gen_cvt_itof1(int t
)
5365 if ((vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
)) ==
5366 (VT_LLONG
| VT_UNSIGNED
)) {
5369 vpush_global_sym(&func_old_type
, TOK___ulltof
);
5370 else if (t
== VT_DOUBLE
)
5371 vpush_global_sym(&func_old_type
, TOK___ulltod
);
5373 vpush_global_sym(&func_old_type
, TOK___ulltold
);
5383 /* generic ftoi for unsigned long long case */
5384 void gen_cvt_ftoi1(int t
)
5388 if (t
== (VT_LLONG
| VT_UNSIGNED
)) {
5389 /* not handled natively */
5390 st
= vtop
->type
.t
& VT_BTYPE
;
5392 vpush_global_sym(&func_old_type
, TOK___fixunssfdi
);
5393 else if (st
== VT_DOUBLE
)
5394 vpush_global_sym(&func_old_type
, TOK___fixunsdfdi
);
5396 vpush_global_sym(&func_old_type
, TOK___fixunsxfdi
);
5401 vtop
->r2
= REG_LRET
;
5407 /* force char or short cast */
5408 void force_charshort_cast(int t
)
5412 /* XXX: add optimization if lvalue : just change type and offset */
5417 if (t
& VT_UNSIGNED
) {
5418 vpushi((1 << bits
) - 1);
5429 /* cast 'vtop' to 'type' */
5430 static void gen_cast(CType
*type
)
5432 int sbt
, dbt
, sf
, df
, c
;
5434 /* special delayed cast for char/short */
5435 /* XXX: in some cases (multiple cascaded casts), it may still
5437 if (vtop
->r
& VT_MUSTCAST
) {
5438 vtop
->r
&= ~VT_MUSTCAST
;
5439 force_charshort_cast(vtop
->type
.t
);
5442 dbt
= type
->t
& (VT_BTYPE
| VT_UNSIGNED
);
5443 sbt
= vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
);
5445 if (sbt
!= dbt
&& !nocode_wanted
) {
5448 c
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5450 /* convert from fp to fp */
5452 /* constant case: we can do it now */
5453 /* XXX: in ISOC, cannot do it if error in convert */
5454 if (dbt
== VT_FLOAT
&& sbt
== VT_DOUBLE
)
5455 vtop
->c
.f
= (float)vtop
->c
.d
;
5456 else if (dbt
== VT_FLOAT
&& sbt
== VT_LDOUBLE
)
5457 vtop
->c
.f
= (float)vtop
->c
.ld
;
5458 else if (dbt
== VT_DOUBLE
&& sbt
== VT_FLOAT
)
5459 vtop
->c
.d
= (double)vtop
->c
.f
;
5460 else if (dbt
== VT_DOUBLE
&& sbt
== VT_LDOUBLE
)
5461 vtop
->c
.d
= (double)vtop
->c
.ld
;
5462 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_FLOAT
)
5463 vtop
->c
.ld
= (long double)vtop
->c
.f
;
5464 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_DOUBLE
)
5465 vtop
->c
.ld
= (long double)vtop
->c
.d
;
5467 /* non constant case: generate code */
5471 /* convert int to fp */
5474 case VT_LLONG
| VT_UNSIGNED
:
5476 /* XXX: add const cases for long long */
5478 case VT_INT
| VT_UNSIGNED
:
5480 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.ui
; break;
5481 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.ui
; break;
5482 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.ui
; break;
5487 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.i
; break;
5488 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.i
; break;
5489 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.i
; break;
5495 #if !defined(TCC_TARGET_ARM)
5502 /* convert fp to int */
5503 /* we handle char/short/etc... with generic code */
5504 if (dbt
!= (VT_INT
| VT_UNSIGNED
) &&
5505 dbt
!= (VT_LLONG
| VT_UNSIGNED
) &&
5510 case VT_LLONG
| VT_UNSIGNED
:
5512 /* XXX: add const cases for long long */
5514 case VT_INT
| VT_UNSIGNED
:
5516 case VT_FLOAT
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5517 case VT_DOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5518 case VT_LDOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5524 case VT_FLOAT
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5525 case VT_DOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5526 case VT_LDOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5534 if (dbt
== VT_INT
&& (type
->t
& (VT_BTYPE
| VT_UNSIGNED
)) != dbt
) {
5535 /* additional cast for char/short/bool... */
5539 } else if ((dbt
& VT_BTYPE
) == VT_LLONG
) {
5540 if ((sbt
& VT_BTYPE
) != VT_LLONG
) {
5541 /* scalar to long long */
5543 if (sbt
== (VT_INT
| VT_UNSIGNED
))
5544 vtop
->c
.ll
= vtop
->c
.ui
;
5546 vtop
->c
.ll
= vtop
->c
.i
;
5548 /* machine independent conversion */
5550 /* generate high word */
5551 if (sbt
== (VT_INT
| VT_UNSIGNED
)) {
5559 /* patch second register */
5560 vtop
[-1].r2
= vtop
->r
;
5564 } else if (dbt
== VT_BOOL
) {
5565 /* scalar to bool */
5568 } else if ((dbt
& VT_BTYPE
) == VT_BYTE
||
5569 (dbt
& VT_BTYPE
) == VT_SHORT
) {
5570 force_charshort_cast(dbt
);
5571 } else if ((dbt
& VT_BTYPE
) == VT_INT
) {
5573 if (sbt
== VT_LLONG
) {
5574 /* from long long: just take low order word */
5578 /* if lvalue and single word type, nothing to do because
5579 the lvalue already contains the real type size (see
5580 VT_LVAL_xxx constants) */
5586 /* return type size. Put alignment at 'a' */
5587 static int type_size(CType
*type
, int *a
)
5592 bt
= type
->t
& VT_BTYPE
;
5593 if (bt
== VT_STRUCT
) {
5598 } else if (bt
== VT_PTR
) {
5599 if (type
->t
& VT_ARRAY
) {
5601 return type_size(&s
->type
, a
) * s
->c
;
5606 } else if (bt
== VT_LDOUBLE
) {
5608 return LDOUBLE_SIZE
;
5609 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
5610 *a
= 4; /* XXX: i386 specific */
5612 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
5615 } else if (bt
== VT_SHORT
) {
5619 /* char, void, function, _Bool */
5625 /* return the pointed type of t */
5626 static inline CType
*pointed_type(CType
*type
)
5628 return &type
->ref
->type
;
5631 /* modify type so that its it is a pointer to type. */
5632 static void mk_pointer(CType
*type
)
5635 s
= sym_push(SYM_FIELD
, type
, 0, -1);
5636 type
->t
= VT_PTR
| (type
->t
& ~VT_TYPE
);
5640 /* compare function types. OLD functions match any new functions */
5641 static int is_compatible_func(CType
*type1
, CType
*type2
)
5647 if (!is_compatible_types(&s1
->type
, &s2
->type
))
5649 /* XXX: not complete */
5650 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
5654 while (s1
!= NULL
) {
5657 if (!is_compatible_types(&s1
->type
, &s2
->type
))
5667 /* return true if type1 and type2 are exactly the same (including
5670 - enums are not checked as gcc __builtin_types_compatible_p ()
5672 static int is_compatible_types(CType
*type1
, CType
*type2
)
5676 t1
= type1
->t
& VT_TYPE
;
5677 t2
= type2
->t
& VT_TYPE
;
5678 /* XXX: bitfields ? */
5681 /* test more complicated cases */
5682 bt1
= t1
& VT_BTYPE
;
5683 if (bt1
== VT_PTR
) {
5684 type1
= pointed_type(type1
);
5685 type2
= pointed_type(type2
);
5686 return is_compatible_types(type1
, type2
);
5687 } else if (bt1
== VT_STRUCT
) {
5688 return (type1
->ref
== type2
->ref
);
5689 } else if (bt1
== VT_FUNC
) {
5690 return is_compatible_func(type1
, type2
);
5696 /* print a type. If 'varstr' is not NULL, then the variable is also
5697 printed in the type */
5699 /* XXX: add array and function pointers */
5700 void type_to_str(char *buf
, int buf_size
,
5701 CType
*type
, const char *varstr
)
5708 t
= type
->t
& VT_TYPE
;
5711 if (t
& VT_CONSTANT
)
5712 pstrcat(buf
, buf_size
, "const ");
5713 if (t
& VT_VOLATILE
)
5714 pstrcat(buf
, buf_size
, "volatile ");
5715 if (t
& VT_UNSIGNED
)
5716 pstrcat(buf
, buf_size
, "unsigned ");
5746 tstr
= "long double";
5748 pstrcat(buf
, buf_size
, tstr
);
5752 if (bt
== VT_STRUCT
)
5756 pstrcat(buf
, buf_size
, tstr
);
5757 v
= type
->ref
->v
& ~SYM_STRUCT
;
5758 if (v
>= SYM_FIRST_ANOM
)
5759 pstrcat(buf
, buf_size
, "<anonymous>");
5761 pstrcat(buf
, buf_size
, get_tok_str(v
, NULL
));
5765 type_to_str(buf
, buf_size
, &s
->type
, varstr
);
5766 pstrcat(buf
, buf_size
, "(");
5768 while (sa
!= NULL
) {
5769 type_to_str(buf1
, sizeof(buf1
), &sa
->type
, NULL
);
5770 pstrcat(buf
, buf_size
, buf1
);
5773 pstrcat(buf
, buf_size
, ", ");
5775 pstrcat(buf
, buf_size
, ")");
5779 pstrcpy(buf1
, sizeof(buf1
), "*");
5781 pstrcat(buf1
, sizeof(buf1
), varstr
);
5782 type_to_str(buf
, buf_size
, &s
->type
, buf1
);
5786 pstrcat(buf
, buf_size
, " ");
5787 pstrcat(buf
, buf_size
, varstr
);
5792 /* verify type compatibility to store vtop in 'dt' type, and generate
5794 static void gen_assign_cast(CType
*dt
)
5796 CType
*st
, *type1
, *type2
, tmp_type1
, tmp_type2
;
5797 char buf1
[256], buf2
[256];
5800 st
= &vtop
->type
; /* source type */
5801 dbt
= dt
->t
& VT_BTYPE
;
5802 sbt
= st
->t
& VT_BTYPE
;
5803 if (dt
->t
& VT_CONSTANT
)
5804 warning("assignment of read-only location");
5807 /* special cases for pointers */
5808 /* '0' can also be a pointer */
5809 if (is_null_pointer(vtop
))
5811 /* accept implicit pointer to integer cast with warning */
5812 if (is_integer_btype(sbt
)) {
5813 warning("assignment makes pointer from integer without a cast");
5816 type1
= pointed_type(dt
);
5817 /* a function is implicitely a function pointer */
5818 if (sbt
== VT_FUNC
) {
5819 if ((type1
->t
& VT_BTYPE
) != VT_VOID
&&
5820 !is_compatible_types(pointed_type(dt
), st
))
5827 type2
= pointed_type(st
);
5828 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
5829 (type2
->t
& VT_BTYPE
) == VT_VOID
) {
5830 /* void * can match anything */
5832 /* exact type match, except for unsigned */
5835 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5836 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5837 if (!is_compatible_types(&tmp_type1
, &tmp_type2
))
5840 /* check const and volatile */
5841 if ((!(type1
->t
& VT_CONSTANT
) && (type2
->t
& VT_CONSTANT
)) ||
5842 (!(type1
->t
& VT_VOLATILE
) && (type2
->t
& VT_VOLATILE
)))
5843 warning("assignment discards qualifiers from pointer target type");
5849 if (sbt
== VT_PTR
|| sbt
== VT_FUNC
) {
5850 warning("assignment makes integer from pointer without a cast");
5852 /* XXX: more tests */
5855 if (!is_compatible_types(dt
, st
)) {
5857 type_to_str(buf1
, sizeof(buf1
), st
, NULL
);
5858 type_to_str(buf2
, sizeof(buf2
), dt
, NULL
);
5859 error("cannot cast '%s' to '%s'", buf1
, buf2
);
5867 /* store vtop in lvalue pushed on stack */
5870 int sbt
, dbt
, ft
, r
, t
, size
, align
, bit_size
, bit_pos
, rc
, delayed_cast
;
5872 ft
= vtop
[-1].type
.t
;
5873 sbt
= vtop
->type
.t
& VT_BTYPE
;
5874 dbt
= ft
& VT_BTYPE
;
5875 if (((sbt
== VT_INT
|| sbt
== VT_SHORT
) && dbt
== VT_BYTE
) ||
5876 (sbt
== VT_INT
&& dbt
== VT_SHORT
)) {
5877 /* optimize char/short casts */
5878 delayed_cast
= VT_MUSTCAST
;
5879 vtop
->type
.t
= ft
& VT_TYPE
;
5880 /* XXX: factorize */
5881 if (ft
& VT_CONSTANT
)
5882 warning("assignment of read-only location");
5885 gen_assign_cast(&vtop
[-1].type
);
5888 if (sbt
== VT_STRUCT
) {
5889 /* if structure, only generate pointer */
5890 /* structure assignment : generate memcpy */
5891 /* XXX: optimize if small size */
5892 if (!nocode_wanted
) {
5893 size
= type_size(&vtop
->type
, &align
);
5895 vpush_global_sym(&func_old_type
, TOK_memcpy
);
5899 vtop
->type
.t
= VT_INT
;
5903 vtop
->type
.t
= VT_INT
;
5915 /* leave source on stack */
5916 } else if (ft
& VT_BITFIELD
) {
5917 /* bitfield store handling */
5918 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
5919 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
5920 /* remove bit field info to avoid loops */
5921 vtop
[-1].type
.t
= ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
5923 /* duplicate destination */
5925 vtop
[-1] = vtop
[-2];
5927 /* mask and shift source */
5928 vpushi((1 << bit_size
) - 1);
5932 /* load destination, mask and or with source */
5934 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
5940 #ifdef CONFIG_TCC_BCHECK
5941 /* bound check case */
5942 if (vtop
[-1].r
& VT_MUSTBOUND
) {
5948 if (!nocode_wanted
) {
5952 r
= gv(rc
); /* generate value */
5953 /* if lvalue was saved on stack, must read it */
5954 if ((vtop
[-1].r
& VT_VALMASK
) == VT_LLOCAL
) {
5956 t
= get_reg(RC_INT
);
5958 sv
.r
= VT_LOCAL
| VT_LVAL
;
5959 sv
.c
.ul
= vtop
[-1].c
.ul
;
5961 vtop
[-1].r
= t
| VT_LVAL
;
5964 /* two word case handling : store second register at word + 4 */
5965 if ((ft
& VT_BTYPE
) == VT_LLONG
) {
5967 /* convert to int to increment easily */
5968 vtop
->type
.t
= VT_INT
;
5974 /* XXX: it works because r2 is spilled last ! */
5975 store(vtop
->r2
, vtop
- 1);
5979 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
5980 vtop
->r
|= delayed_cast
;
5984 /* post defines POST/PRE add. c is the token ++ or -- */
5985 void inc(int post
, int c
)
5988 vdup(); /* save lvalue */
5990 gv_dup(); /* duplicate value */
5995 vpushi(c
- TOK_MID
);
5997 vstore(); /* store value */
5999 vpop(); /* if post op, return saved value */
6002 /* Parse GNUC __attribute__ extension. Currently, the following
6003 extensions are recognized:
6004 - aligned(n) : set data/function alignment.
6005 - section(x) : generate data/code in this section.
6006 - unused : currently ignored, but may be used someday.
6008 static void parse_attribute(AttributeDef
*ad
)
6012 while (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
) {
6016 while (tok
!= ')') {
6017 if (tok
< TOK_IDENT
)
6018 expect("attribute name");
6026 expect("section name");
6027 ad
->section
= find_section(tcc_state
, (char *)tokc
.cstr
->data
);
6036 if (n
<= 0 || (n
& (n
- 1)) != 0)
6037 error("alignment must be a positive power of two");
6046 /* currently, no need to handle it because tcc does not
6047 track unused objects */
6051 /* currently, no need to handle it because tcc does not
6052 track unused objects */
6057 ad
->func_call
= FUNC_CDECL
;
6062 ad
->func_call
= FUNC_STDCALL
;
6065 if (tcc_state
->warn_unsupported
)
6066 warning("'%s' attribute ignored", get_tok_str(t
, NULL
));
6067 /* skip parameters */
6068 /* XXX: skip parenthesis too */
6071 while (tok
!= ')' && tok
!= -1)
6086 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6087 static void struct_decl(CType
*type
, int u
)
6089 int a
, v
, size
, align
, maxalign
, c
, offset
;
6090 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
;
6095 a
= tok
; /* save decl type */
6100 /* struct already defined ? return it */
6102 expect("struct/union/enum name");
6106 error("invalid type");
6113 /* we put an undefined size for struct/union */
6114 s
= sym_push(v
| SYM_STRUCT
, &type1
, 0, -1);
6115 s
->r
= 0; /* default alignment is zero as gcc */
6116 /* put struct/union/enum name in type */
6124 error("struct/union/enum already defined");
6125 /* cannot be empty */
6127 /* non empty enums are not allowed */
6128 if (a
== TOK_ENUM
) {
6132 expect("identifier");
6138 /* enum symbols have static storage */
6139 ss
= sym_push(v
, &int_type
, VT_CONST
, c
);
6140 ss
->type
.t
|= VT_STATIC
;
6145 /* NOTE: we accept a trailing comma */
6155 while (tok
!= '}') {
6156 parse_btype(&btype
, &ad
);
6162 type_decl(&type1
, &ad
, &v
, TYPE_DIRECT
);
6163 if ((type1
.t
& VT_BTYPE
) == VT_FUNC
||
6164 (type1
.t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
| VT_INLINE
)))
6165 error("invalid type for '%s'",
6166 get_tok_str(v
, NULL
));
6170 bit_size
= expr_const();
6171 /* XXX: handle v = 0 case for messages */
6173 error("negative width in bit-field '%s'",
6174 get_tok_str(v
, NULL
));
6175 if (v
&& bit_size
== 0)
6176 error("zero width for bit-field '%s'",
6177 get_tok_str(v
, NULL
));
6179 size
= type_size(&type1
, &align
);
6181 if (bit_size
>= 0) {
6182 bt
= type1
.t
& VT_BTYPE
;
6187 error("bitfields must have scalar type");
6189 if (bit_size
> bsize
) {
6190 error("width of '%s' exceeds its type",
6191 get_tok_str(v
, NULL
));
6192 } else if (bit_size
== bsize
) {
6193 /* no need for bit fields */
6195 } else if (bit_size
== 0) {
6196 /* XXX: what to do if only padding in a
6198 /* zero size: means to pad */
6202 /* we do not have enough room ? */
6203 if ((bit_pos
+ bit_size
) > bsize
)
6206 /* XXX: handle LSB first */
6207 type1
.t
|= VT_BITFIELD
|
6208 (bit_pos
<< VT_STRUCT_SHIFT
) |
6209 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
6210 bit_pos
+= bit_size
;
6216 /* add new memory data only if starting
6218 if (lbit_pos
== 0) {
6219 if (a
== TOK_STRUCT
) {
6220 c
= (c
+ align
- 1) & -align
;
6228 if (align
> maxalign
)
6232 printf("add field %s offset=%d",
6233 get_tok_str(v
, NULL
), offset
);
6234 if (type1
.t
& VT_BITFIELD
) {
6235 printf(" pos=%d size=%d",
6236 (type1
.t
>> VT_STRUCT_SHIFT
) & 0x3f,
6237 (type1
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
6241 ss
= sym_push(v
| SYM_FIELD
, &type1
, 0, offset
);
6245 if (tok
== ';' || tok
== TOK_EOF
)
6252 /* store size and alignment */
6253 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
6259 /* return 0 if no type declaration. otherwise, return the basic type
6262 static int parse_btype(CType
*type
, AttributeDef
*ad
)
6264 int t
, u
, type_found
, typespec_found
;
6268 memset(ad
, 0, sizeof(AttributeDef
));
6275 /* currently, we really ignore extension */
6285 if ((t
& VT_BTYPE
) != 0)
6286 error("too many basic types");
6302 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
6303 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6304 } else if ((t
& VT_BTYPE
) == VT_LONG
) {
6305 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
6319 if ((t
& VT_BTYPE
) == VT_LONG
) {
6320 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6327 struct_decl(&type1
, VT_ENUM
);
6330 type
->ref
= type1
.ref
;
6334 struct_decl(&type1
, VT_STRUCT
);
6337 /* type modifiers */
6390 /* GNUC attribute */
6391 case TOK_ATTRIBUTE1
:
6392 case TOK_ATTRIBUTE2
:
6393 parse_attribute(ad
);
6400 parse_expr_type(&type1
);
6406 if (!s
|| !(s
->type
.t
& VT_TYPEDEF
))
6408 t
|= (s
->type
.t
& ~VT_TYPEDEF
);
6409 type
->ref
= s
->type
.ref
;
6416 if ((t
& (VT_SIGNED
|VT_UNSIGNED
)) == (VT_SIGNED
|VT_UNSIGNED
))
6417 error("signed and unsigned modifier");
6418 #ifdef CHAR_IS_UNSIGNED
6419 if ((t
& (VT_SIGNED
|VT_UNSIGNED
|VT_BTYPE
)) == VT_BYTE
)
6424 /* long is never used as type */
6425 if ((t
& VT_BTYPE
) == VT_LONG
)
6426 t
= (t
& ~VT_BTYPE
) | VT_INT
;
6431 /* convert a function parameter type (array to pointer and function to
6432 function pointer) */
6433 static inline void convert_parameter_type(CType
*pt
)
6435 /* array must be transformed to pointer according to ANSI C */
6437 if ((pt
->t
& VT_BTYPE
) == VT_FUNC
) {
6442 static void post_type(CType
*type
, AttributeDef
*ad
)
6445 Sym
**plast
, *s
, *first
;
6450 /* function declaration */
6455 while (tok
!= ')') {
6456 /* read param name and compute offset */
6457 if (l
!= FUNC_OLD
) {
6458 if (!parse_btype(&pt
, &ad1
)) {
6460 error("invalid type");
6467 if ((pt
.t
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
6469 type_decl(&pt
, &ad1
, &n
, TYPE_DIRECT
| TYPE_ABSTRACT
);
6470 if ((pt
.t
& VT_BTYPE
) == VT_VOID
)
6471 error("parameter declared as void");
6478 convert_parameter_type(&pt
);
6479 s
= sym_push(n
| SYM_FIELD
, &pt
, 0, 0);
6484 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
6491 /* if no parameters, then old type prototype */
6495 t1
= type
->t
& VT_STORAGE
;
6496 /* NOTE: const is ignored in returned type as it has a special
6497 meaning in gcc / C++ */
6498 type
->t
&= ~(VT_STORAGE
| VT_CONSTANT
);
6499 post_type(type
, ad
);
6500 /* we push a anonymous symbol which will contain the function prototype */
6501 s
= sym_push(SYM_FIELD
, type
, ad
->func_call
, l
);
6503 type
->t
= t1
| VT_FUNC
;
6505 } else if (tok
== '[') {
6506 /* array definition */
6512 error("invalid array size");
6515 /* parse next post type */
6516 t1
= type
->t
& VT_STORAGE
;
6517 type
->t
&= ~VT_STORAGE
;
6518 post_type(type
, ad
);
6520 /* we push a anonymous symbol which will contain the array
6522 s
= sym_push(SYM_FIELD
, type
, 0, n
);
6523 type
->t
= t1
| VT_ARRAY
| VT_PTR
;
6528 /* Parse a type declaration (except basic type), and return the type
6529 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6530 expected. 'type' should contain the basic type. 'ad' is the
6531 attribute definition of the basic type. It can be modified by
6534 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
)
6537 CType type1
, *type2
;
6540 while (tok
== '*') {
6548 qualifiers
|= VT_CONSTANT
;
6553 qualifiers
|= VT_VOLATILE
;
6561 type
->t
|= qualifiers
;
6564 /* XXX: clarify attribute handling */
6565 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
6566 parse_attribute(ad
);
6568 /* recursive type */
6569 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6570 type1
.t
= 0; /* XXX: same as int */
6573 /* XXX: this is not correct to modify 'ad' at this point, but
6574 the syntax is not clear */
6575 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
6576 parse_attribute(ad
);
6577 type_decl(&type1
, ad
, v
, td
);
6580 /* type identifier */
6581 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
6585 if (!(td
& TYPE_ABSTRACT
))
6586 expect("identifier");
6590 post_type(type
, ad
);
6591 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
6592 parse_attribute(ad
);
6595 /* append type at the end of type1 */
6608 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6609 static int lvalue_type(int t
)
6614 if (bt
== VT_BYTE
|| bt
== VT_BOOL
)
6616 else if (bt
== VT_SHORT
)
6620 if (t
& VT_UNSIGNED
)
6621 r
|= VT_LVAL_UNSIGNED
;
6625 /* indirection with full error checking and bound check */
6626 static void indir(void)
6628 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
6630 if ((vtop
->r
& VT_LVAL
) && !nocode_wanted
)
6632 vtop
->type
= *pointed_type(&vtop
->type
);
6633 /* an array is never an lvalue */
6634 if (!(vtop
->type
.t
& VT_ARRAY
)) {
6635 vtop
->r
|= lvalue_type(vtop
->type
.t
);
6636 /* if bound checking, the referenced pointer must be checked */
6637 if (do_bounds_check
)
6638 vtop
->r
|= VT_MUSTBOUND
;
6642 /* pass a parameter to a function and do type checking and casting */
6643 static void gfunc_param_typed(Sym
*func
, Sym
*arg
)
6648 func_type
= func
->c
;
6649 if (func_type
== FUNC_OLD
||
6650 (func_type
== FUNC_ELLIPSIS
&& arg
== NULL
)) {
6651 /* default casting : only need to convert float to double */
6652 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FLOAT
) {
6656 } else if (arg
== NULL
) {
6657 error("too many arguments to function");
6660 type
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
6661 gen_assign_cast(&type
);
6665 /* parse an expression of the form '(type)' or '(expr)' and return its
6667 static void parse_expr_type(CType
*type
)
6673 if (parse_btype(type
, &ad
)) {
6674 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
6681 static void parse_type(CType
*type
)
6686 if (!parse_btype(type
, &ad
)) {
6689 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
6692 static void vpush_tokc(int t
)
6696 vsetc(&type
, VT_CONST
, &tokc
);
6699 static void unary(void)
6701 int n
, t
, align
, size
, r
;
6706 /* XXX: GCC 2.95.3 does not generate a table although it should be
6720 vpush_tokc(VT_INT
| VT_UNSIGNED
);
6724 vpush_tokc(VT_LLONG
);
6728 vpush_tokc(VT_LLONG
| VT_UNSIGNED
);
6732 vpush_tokc(VT_FLOAT
);
6736 vpush_tokc(VT_DOUBLE
);
6740 vpush_tokc(VT_LDOUBLE
);
6743 case TOK___FUNCTION__
:
6745 goto tok_identifier
;
6751 /* special function name identifier */
6752 len
= strlen(funcname
) + 1;
6753 /* generate char[len] type */
6758 vpush_ref(&type
, data_section
, data_section
->data_offset
, len
);
6759 ptr
= section_ptr_add(data_section
, len
);
6760 memcpy(ptr
, funcname
, len
);
6768 /* string parsing */
6771 if (tcc_state
->warn_write_strings
)
6776 memset(&ad
, 0, sizeof(AttributeDef
));
6777 decl_initializer_alloc(&type
, &ad
, VT_CONST
, 2, 0, 0);
6782 if (parse_btype(&type
, &ad
)) {
6783 type_decl(&type
, &ad
, &n
, TYPE_ABSTRACT
);
6785 /* check ISOC99 compound literal */
6787 /* data is allocated locally by default */
6792 /* all except arrays are lvalues */
6793 if (!(type
.t
& VT_ARRAY
))
6794 r
|= lvalue_type(type
.t
);
6795 memset(&ad
, 0, sizeof(AttributeDef
));
6796 decl_initializer_alloc(&type
, &ad
, r
, 1, 0, 0);
6801 } else if (tok
== '{') {
6802 /* save all registers */
6804 /* statement expression : we do not accept break/continue
6805 inside as GCC does */
6806 block(NULL
, NULL
, NULL
, NULL
, 0, 1);
6821 /* functions names must be treated as function pointers,
6822 except for unary '&' and sizeof. Since we consider that
6823 functions are not lvalues, we only have to handle it
6824 there and in function calls. */
6825 /* arrays can also be used although they are not lvalues */
6826 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
&&
6827 !(vtop
->type
.t
& VT_ARRAY
))
6829 mk_pointer(&vtop
->type
);
6835 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
)
6836 vtop
->c
.i
= !vtop
->c
.i
;
6837 else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
6838 vtop
->c
.i
= vtop
->c
.i
^ 1;
6840 vseti(VT_JMP
, gtst(1, 0));
6850 /* in order to force cast, we add zero */
6852 if ((vtop
->type
.t
& VT_BTYPE
) == VT_PTR
)
6853 error("pointer not accepted for unary plus");
6863 parse_expr_type(&type
);
6867 size
= type_size(&type
, &align
);
6868 if (t
== TOK_SIZEOF
) {
6870 error("sizeof applied to an incomplete type");
6877 case TOK_builtin_types_compatible_p
:
6886 type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6887 type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6888 vpushi(is_compatible_types(&type1
, &type2
));
6891 case TOK_builtin_constant_p
:
6893 int saved_nocode_wanted
, res
;
6896 saved_nocode_wanted
= nocode_wanted
;
6899 res
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
6901 nocode_wanted
= saved_nocode_wanted
;
6921 goto tok_identifier
;
6923 /* allow to take the address of a label */
6924 if (tok
< TOK_UIDENT
)
6925 expect("label identifier");
6926 s
= label_find(tok
);
6928 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
6930 if (s
->r
== LABEL_DECLARED
)
6931 s
->r
= LABEL_FORWARD
;
6934 s
->type
.t
= VT_VOID
;
6935 mk_pointer(&s
->type
);
6936 s
->type
.t
|= VT_STATIC
;
6938 vset(&s
->type
, VT_CONST
| VT_SYM
, 0);
6947 expect("identifier");
6951 error("'%s' undeclared", get_tok_str(t
, NULL
));
6952 /* for simple function calls, we tolerate undeclared
6953 external reference to int() function */
6954 s
= external_global_sym(t
, &func_old_type
, 0);
6956 vset(&s
->type
, s
->r
, s
->c
);
6957 /* if forward reference, we must point to s */
6958 if (vtop
->r
& VT_SYM
) {
6965 /* post operations */
6967 if (tok
== TOK_INC
|| tok
== TOK_DEC
) {
6970 } else if (tok
== '.' || tok
== TOK_ARROW
) {
6972 if (tok
== TOK_ARROW
)
6977 /* expect pointer on structure */
6978 if ((vtop
->type
.t
& VT_BTYPE
) != VT_STRUCT
)
6979 expect("struct or union");
6983 while ((s
= s
->next
) != NULL
) {
6988 error("field not found");
6989 /* add field offset to pointer */
6990 vtop
->type
= char_pointer_type
; /* change type to 'char *' */
6993 /* change type to field type, and set to lvalue */
6994 vtop
->type
= s
->type
;
6995 /* an array is never an lvalue */
6996 if (!(vtop
->type
.t
& VT_ARRAY
)) {
6997 vtop
->r
|= lvalue_type(vtop
->type
.t
);
6998 /* if bound checking, the referenced pointer must be checked */
6999 if (do_bounds_check
)
7000 vtop
->r
|= VT_MUSTBOUND
;
7003 } else if (tok
== '[') {
7009 } else if (tok
== '(') {
7015 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
) {
7016 /* pointer test (no array accepted) */
7017 if ((vtop
->type
.t
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
7018 vtop
->type
= *pointed_type(&vtop
->type
);
7019 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
)
7023 expect("function pointer");
7026 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
7028 /* get return type */
7031 sa
= s
->next
; /* first parameter */
7033 /* compute first implicit argument if a structure is returned */
7034 if ((s
->type
.t
& VT_BTYPE
) == VT_STRUCT
) {
7035 /* get some space for the returned structure */
7036 size
= type_size(&s
->type
, &align
);
7037 loc
= (loc
- size
) & -align
;
7039 ret
.r
= VT_LOCAL
| VT_LVAL
;
7040 /* pass it as 'int' to avoid structure arg passing
7042 vseti(VT_LOCAL
, loc
);
7048 /* return in register */
7049 if (is_float(ret
.type
.t
)) {
7052 if ((ret
.type
.t
& VT_BTYPE
) == VT_LLONG
)
7061 gfunc_param_typed(s
, sa
);
7071 error("too few arguments to function");
7073 if (!nocode_wanted
) {
7074 gfunc_call(nb_args
);
7076 vtop
-= (nb_args
+ 1);
7079 vsetc(&ret
.type
, ret
.r
, &ret
.c
);
7087 static void uneq(void)
7093 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
7094 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
7095 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
7110 static void expr_prod(void)
7115 while (tok
== '*' || tok
== '/' || tok
== '%') {
7123 static void expr_sum(void)
7128 while (tok
== '+' || tok
== '-') {
7136 static void expr_shift(void)
7141 while (tok
== TOK_SHL
|| tok
== TOK_SAR
) {
7149 static void expr_cmp(void)
7154 while ((tok
>= TOK_ULE
&& tok
<= TOK_GT
) ||
7155 tok
== TOK_ULT
|| tok
== TOK_UGE
) {
7163 static void expr_cmpeq(void)
7168 while (tok
== TOK_EQ
|| tok
== TOK_NE
) {
7176 static void expr_and(void)
7179 while (tok
== '&') {
7186 static void expr_xor(void)
7189 while (tok
== '^') {
7196 static void expr_or(void)
7199 while (tok
== '|') {
7206 /* XXX: fix this mess */
7207 static void expr_land_const(void)
7210 while (tok
== TOK_LAND
) {
7217 /* XXX: fix this mess */
7218 static void expr_lor_const(void)
7221 while (tok
== TOK_LOR
) {
7228 /* only used if non constant */
7229 static void expr_land(void)
7234 if (tok
== TOK_LAND
) {
7238 if (tok
!= TOK_LAND
) {
7248 static void expr_lor(void)
7253 if (tok
== TOK_LOR
) {
7257 if (tok
!= TOK_LOR
) {
7267 /* XXX: better constant handling */
7268 static void expr_eq(void)
7270 int tt
, u
, r1
, r2
, rc
, t1
, t2
, bt1
, bt2
;
7272 CType type
, type1
, type2
;
7281 if (tok
== ':' && gnu_ext
) {
7297 if (vtop
!= vstack
) {
7298 /* needed to avoid having different registers saved in
7300 if (is_float(vtop
->type
.t
))
7307 if (tok
== ':' && gnu_ext
) {
7315 sv
= *vtop
; /* save value to handle it later */
7316 vtop
--; /* no vpop so that FP stack is not flushed */
7324 bt1
= t1
& VT_BTYPE
;
7326 bt2
= t2
& VT_BTYPE
;
7327 /* cast operands to correct type according to ISOC rules */
7328 if (is_float(bt1
) || is_float(bt2
)) {
7329 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
7330 type
.t
= VT_LDOUBLE
;
7331 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
7336 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
7337 /* cast to biggest op */
7339 /* convert to unsigned if it does not fit in a long long */
7340 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
7341 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
7342 type
.t
|= VT_UNSIGNED
;
7343 } else if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
7344 /* XXX: test pointer compatibility */
7346 } else if (bt1
== VT_STRUCT
|| bt2
== VT_STRUCT
) {
7347 /* XXX: test structure compatibility */
7349 } else if (bt1
== VT_VOID
|| bt2
== VT_VOID
) {
7350 /* NOTE: as an extension, we accept void on only one side */
7353 /* integer operations */
7355 /* convert to unsigned if it does not fit in an integer */
7356 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
7357 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
7358 type
.t
|= VT_UNSIGNED
;
7361 /* now we convert second operand */
7364 if (is_float(type
.t
)) {
7366 } else if ((type
.t
& VT_BTYPE
) == VT_LLONG
) {
7367 /* for long longs, we use fixed registers to avoid having
7368 to handle a complicated move */
7373 /* this is horrible, but we must also convert first
7377 /* put again first value and cast it */
7388 static void gexpr(void)
7399 /* parse an expression and return its type without any side effect. */
7400 static void expr_type(CType
*type
)
7402 int saved_nocode_wanted
;
7404 saved_nocode_wanted
= nocode_wanted
;
7409 nocode_wanted
= saved_nocode_wanted
;
7412 /* parse a unary expression and return its type without any side
7414 static void unary_type(CType
*type
)
7426 /* parse a constant expression and return value in vtop. */
7427 static void expr_const1(void)
7436 /* parse an integer constant and return its value. */
7437 static int expr_const(void)
7441 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
7442 expect("constant expression");
7448 /* return the label token if current token is a label, otherwise
7450 static int is_label(void)
7454 /* fast test first */
7455 if (tok
< TOK_UIDENT
)
7457 /* no need to save tokc because tok is an identifier */
7464 unget_tok(last_tok
);
7469 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
7470 int case_reg
, int is_expr
)
7475 /* generate line number info */
7477 (last_line_num
!= file
->line_num
|| last_ind
!= ind
)) {
7478 put_stabn(N_SLINE
, 0, file
->line_num
, ind
- func_ind
);
7480 last_line_num
= file
->line_num
;
7484 /* default return value is (void) */
7486 vtop
->type
.t
= VT_VOID
;
7489 if (tok
== TOK_IF
) {
7496 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
7498 if (c
== TOK_ELSE
) {
7502 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
7503 gsym(d
); /* patch else jmp */
7506 } else if (tok
== TOK_WHILE
) {
7514 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
7518 } else if (tok
== '{') {
7522 /* record local declaration stack position */
7524 llabel
= local_label_stack
;
7525 /* handle local labels declarations */
7526 if (tok
== TOK_LABEL
) {
7529 if (tok
< TOK_UIDENT
)
7530 expect("label identifier");
7531 label_push(&local_label_stack
, tok
, LABEL_DECLARED
);
7541 while (tok
!= '}') {
7546 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
7549 /* pop locally defined labels */
7550 label_pop(&local_label_stack
, llabel
);
7551 /* pop locally defined symbols */
7552 sym_pop(&local_stack
, s
);
7554 } else if (tok
== TOK_RETURN
) {
7558 gen_assign_cast(&func_vt
);
7559 if ((func_vt
.t
& VT_BTYPE
) == VT_STRUCT
) {
7561 /* if returning structure, must copy it to implicit
7562 first pointer arg location */
7565 vset(&type
, VT_LOCAL
| VT_LVAL
, func_vc
);
7568 /* copy structure value to pointer */
7570 } else if (is_float(func_vt
.t
)) {
7575 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
7578 rsym
= gjmp(rsym
); /* jmp */
7579 } else if (tok
== TOK_BREAK
) {
7582 error("cannot break");
7583 *bsym
= gjmp(*bsym
);
7586 } else if (tok
== TOK_CONTINUE
) {
7589 error("cannot continue");
7590 *csym
= gjmp(*csym
);
7593 } else if (tok
== TOK_FOR
) {
7620 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
7625 if (tok
== TOK_DO
) {
7630 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
7641 if (tok
== TOK_SWITCH
) {
7645 /* XXX: other types than integer */
7646 case_reg
= gv(RC_INT
);
7650 b
= gjmp(0); /* jump to first case */
7652 block(&a
, csym
, &b
, &c
, case_reg
, 0);
7653 /* if no default, jmp after switch */
7661 if (tok
== TOK_CASE
) {
7668 if (gnu_ext
&& tok
== TOK_DOTS
) {
7672 warning("empty case range");
7674 /* since a case is like a label, we must skip it with a jmp */
7681 *case_sym
= gtst(1, 0);
7684 *case_sym
= gtst(1, 0);
7688 *case_sym
= gtst(1, *case_sym
);
7693 goto block_after_label
;
7695 if (tok
== TOK_DEFAULT
) {
7701 error("too many 'default'");
7704 goto block_after_label
;
7706 if (tok
== TOK_GOTO
) {
7708 if (tok
== '*' && gnu_ext
) {
7712 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
7715 } else if (tok
>= TOK_UIDENT
) {
7716 s
= label_find(tok
);
7717 /* put forward definition if needed */
7719 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
7721 if (s
->r
== LABEL_DECLARED
)
7722 s
->r
= LABEL_FORWARD
;
7724 /* label already defined */
7725 if (s
->r
& LABEL_FORWARD
)
7726 s
->next
= (void *)gjmp((long)s
->next
);
7728 gjmp_addr((long)s
->next
);
7731 expect("label identifier");
7734 } else if (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
) {
7742 if (s
->r
== LABEL_DEFINED
)
7743 error("duplicate label '%s'", get_tok_str(s
->v
, NULL
));
7744 gsym((long)s
->next
);
7745 s
->r
= LABEL_DEFINED
;
7747 s
= label_push(&global_label_stack
, b
, LABEL_DEFINED
);
7749 s
->next
= (void *)ind
;
7750 /* we accept this, but it is a mistake */
7753 warning("deprecated use of label at end of compound statement");
7757 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
7760 /* expression case */
7775 /* t is the array or struct type. c is the array or struct
7776 address. cur_index/cur_field is the pointer to the current
7777 value. 'size_only' is true if only size info is needed (only used
7779 static void decl_designator(CType
*type
, Section
*sec
, unsigned long c
,
7780 int *cur_index
, Sym
**cur_field
,
7784 int notfirst
, index
, index_last
, align
, l
, nb_elems
, elem_size
;
7790 if (gnu_ext
&& (l
= is_label()) != 0)
7792 while (tok
== '[' || tok
== '.') {
7794 if (!(type
->t
& VT_ARRAY
))
7795 expect("array type");
7798 index
= expr_const();
7799 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
7800 expect("invalid index");
7801 if (tok
== TOK_DOTS
&& gnu_ext
) {
7803 index_last
= expr_const();
7804 if (index_last
< 0 ||
7805 (s
->c
>= 0 && index_last
>= s
->c
) ||
7807 expect("invalid index");
7813 *cur_index
= index_last
;
7814 type
= pointed_type(type
);
7815 elem_size
= type_size(type
, &align
);
7816 c
+= index
* elem_size
;
7817 /* NOTE: we only support ranges for last designator */
7818 nb_elems
= index_last
- index
+ 1;
7819 if (nb_elems
!= 1) {
7828 if ((type
->t
& VT_BTYPE
) != VT_STRUCT
)
7829 expect("struct/union type");
7842 /* XXX: fix this mess by using explicit storage field */
7844 type1
.t
|= (type
->t
& ~VT_TYPE
);
7858 if (type
->t
& VT_ARRAY
) {
7860 type
= pointed_type(type
);
7861 c
+= index
* type_size(type
, &align
);
7865 error("too many field init");
7866 /* XXX: fix this mess by using explicit storage field */
7868 type1
.t
|= (type
->t
& ~VT_TYPE
);
7873 decl_initializer(type
, sec
, c
, 0, size_only
);
7875 /* XXX: make it more general */
7876 if (!size_only
&& nb_elems
> 1) {
7877 unsigned long c_end
;
7882 error("range init not supported yet for dynamic storage");
7883 c_end
= c
+ nb_elems
* elem_size
;
7884 if (c_end
> sec
->data_allocated
)
7885 section_realloc(sec
, c_end
);
7886 src
= sec
->data
+ c
;
7888 for(i
= 1; i
< nb_elems
; i
++) {
7890 memcpy(dst
, src
, elem_size
);
7896 #define EXPR_CONST 1
7899 /* store a value or an expression directly in global data or in local array */
7900 static void init_putv(CType
*type
, Section
*sec
, unsigned long c
,
7901 int v
, int expr_type
)
7903 int saved_global_expr
, bt
, bit_pos
, bit_size
;
7905 unsigned long long bit_mask
;
7913 /* compound literals must be allocated globally in this case */
7914 saved_global_expr
= global_expr
;
7917 global_expr
= saved_global_expr
;
7918 /* NOTE: symbols are accepted */
7919 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) != VT_CONST
)
7920 error("initializer element is not constant");
7928 dtype
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
7931 /* XXX: not portable */
7932 /* XXX: generate error if incorrect relocation */
7933 gen_assign_cast(&dtype
);
7934 bt
= type
->t
& VT_BTYPE
;
7935 ptr
= sec
->data
+ c
;
7936 /* XXX: make code faster ? */
7937 if (!(type
->t
& VT_BITFIELD
)) {
7942 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
7943 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
7944 bit_mask
= (1LL << bit_size
) - 1;
7946 if ((vtop
->r
& VT_SYM
) &&
7952 (bt
== VT_INT
&& bit_size
!= 32)))
7953 error("initializer element is not computable at load time");
7956 *(char *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
7959 *(short *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
7962 *(double *)ptr
= vtop
->c
.d
;
7965 *(long double *)ptr
= vtop
->c
.ld
;
7968 *(long long *)ptr
|= (vtop
->c
.ll
& bit_mask
) << bit_pos
;
7971 if (vtop
->r
& VT_SYM
) {
7972 greloc(sec
, vtop
->sym
, c
, R_DATA_32
);
7974 *(int *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
7979 vset(&dtype
, VT_LOCAL
, c
);
7986 /* put zeros for variable based init */
7987 static void init_putz(CType
*t
, Section
*sec
, unsigned long c
, int size
)
7990 /* nothing to do because globals are already set to zero */
7992 vpush_global_sym(&func_old_type
, TOK_memset
);
8000 /* 't' contains the type and storage info. 'c' is the offset of the
8001 object in section 'sec'. If 'sec' is NULL, it means stack based
8002 allocation. 'first' is true if array '{' must be read (multi
8003 dimension implicit array init handling). 'size_only' is true if
8004 size only evaluation is wanted (only for arrays). */
8005 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
8006 int first
, int size_only
)
8008 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
8009 int size1
, align1
, expr_type
;
8013 if (type
->t
& VT_ARRAY
) {
8017 t1
= pointed_type(type
);
8018 size1
= type_size(t1
, &align1
);
8021 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
8027 /* only parse strings here if correct type (otherwise: handle
8028 them as ((w)char *) expressions */
8029 if ((tok
== TOK_LSTR
&&
8030 (t1
->t
& VT_BTYPE
) == VT_INT
) ||
8032 (t1
->t
& VT_BTYPE
) == VT_BYTE
)) {
8033 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8038 /* compute maximum number of chars wanted */
8040 cstr_len
= cstr
->size
;
8042 cstr_len
= cstr
->size
/ sizeof(int);
8045 if (n
>= 0 && nb
> (n
- array_length
))
8046 nb
= n
- array_length
;
8049 warning("initializer-string for array is too long");
8050 /* in order to go faster for common case (char
8051 string in global variable, we handle it
8053 if (sec
&& tok
== TOK_STR
&& size1
== 1) {
8054 memcpy(sec
->data
+ c
+ array_length
, cstr
->data
, nb
);
8058 ch
= ((unsigned char *)cstr
->data
)[i
];
8060 ch
= ((int *)cstr
->data
)[i
];
8061 init_putv(t1
, sec
, c
+ (array_length
+ i
) * size1
,
8069 /* only add trailing zero if enough storage (no
8070 warning in this case since it is standard) */
8071 if (n
< 0 || array_length
< n
) {
8073 init_putv(t1
, sec
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
8079 while (tok
!= '}') {
8080 decl_designator(type
, sec
, c
, &index
, NULL
, size_only
);
8081 if (n
>= 0 && index
>= n
)
8082 error("index too large");
8083 /* must put zero in holes (note that doing it that way
8084 ensures that it even works with designators) */
8085 if (!size_only
&& array_length
< index
) {
8086 init_putz(t1
, sec
, c
+ array_length
* size1
,
8087 (index
- array_length
) * size1
);
8090 if (index
> array_length
)
8091 array_length
= index
;
8092 /* special test for multi dimensional arrays (may not
8093 be strictly correct if designators are used at the
8095 if (index
>= n
&& no_oblock
)
8104 /* put zeros at the end */
8105 if (!size_only
&& n
>= 0 && array_length
< n
) {
8106 init_putz(t1
, sec
, c
+ array_length
* size1
,
8107 (n
- array_length
) * size1
);
8109 /* patch type size if needed */
8111 s
->c
= array_length
;
8112 } else if ((type
->t
& VT_BTYPE
) == VT_STRUCT
&&
8113 (sec
|| !first
|| tok
== '{')) {
8116 /* NOTE: the previous test is a specific case for automatic
8117 struct/union init */
8118 /* XXX: union needs only one init */
8120 /* XXX: this test is incorrect for local initializers
8121 beginning with ( without {. It would be much more difficult
8122 to do it correctly (ideally, the expression parser should
8123 be used in all cases) */
8129 while (tok
== '(') {
8133 if (!parse_btype(&type1
, &ad1
))
8135 type_decl(&type1
, &ad1
, &n
, TYPE_ABSTRACT
);
8137 if (!is_assignable_types(type
, &type1
))
8138 error("invalid type for cast");
8143 if (first
|| tok
== '{') {
8152 while (tok
!= '}') {
8153 decl_designator(type
, sec
, c
, NULL
, &f
, size_only
);
8155 if (!size_only
&& array_length
< index
) {
8156 init_putz(type
, sec
, c
+ array_length
,
8157 index
- array_length
);
8159 index
= index
+ type_size(&f
->type
, &align1
);
8160 if (index
> array_length
)
8161 array_length
= index
;
8163 if (no_oblock
&& f
== NULL
)
8169 /* put zeros at the end */
8170 if (!size_only
&& array_length
< n
) {
8171 init_putz(type
, sec
, c
+ array_length
,
8180 } else if (tok
== '{') {
8182 decl_initializer(type
, sec
, c
, first
, size_only
);
8184 } else if (size_only
) {
8185 /* just skip expression */
8187 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
8191 else if (tok
== ')')
8196 /* currently, we always use constant expression for globals
8197 (may change for scripting case) */
8198 expr_type
= EXPR_CONST
;
8200 expr_type
= EXPR_ANY
;
8201 init_putv(type
, sec
, c
, 0, expr_type
);
8205 /* parse an initializer for type 't' if 'has_init' is non zero, and
8206 allocate space in local or global data space ('r' is either
8207 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8208 variable 'v' of scope 'scope' is declared before initializers are
8209 parsed. If 'v' is zero, then a reference to the new object is put
8210 in the value stack. If 'has_init' is 2, a special parsing is done
8211 to handle string constants. */
8212 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
8213 int has_init
, int v
, int scope
)
8215 int size
, align
, addr
, data_offset
;
8217 ParseState saved_parse_state
;
8218 TokenString init_str
;
8221 size
= type_size(type
, &align
);
8222 /* If unknown size, we must evaluate it before
8223 evaluating initializers because
8224 initializers can generate global data too
8225 (e.g. string pointers or ISOC99 compound
8226 literals). It also simplifies local
8227 initializers handling */
8228 tok_str_new(&init_str
);
8231 error("unknown type size");
8232 /* get all init string */
8233 if (has_init
== 2) {
8234 /* only get strings */
8235 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8236 tok_str_add_tok(&init_str
);
8241 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
8243 error("unexpected end of file in initializer");
8244 tok_str_add_tok(&init_str
);
8247 else if (tok
== '}') {
8255 tok_str_add(&init_str
, -1);
8256 tok_str_add(&init_str
, 0);
8259 save_parse_state(&saved_parse_state
);
8261 macro_ptr
= init_str
.str
;
8263 decl_initializer(type
, NULL
, 0, 1, 1);
8264 /* prepare second initializer parsing */
8265 macro_ptr
= init_str
.str
;
8268 /* if still unknown size, error */
8269 size
= type_size(type
, &align
);
8271 error("unknown type size");
8273 /* take into account specified alignment if bigger */
8274 if (ad
->aligned
> align
)
8275 align
= ad
->aligned
;
8276 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
8278 if (do_bounds_check
&& (type
->t
& VT_ARRAY
))
8280 loc
= (loc
- size
) & -align
;
8282 /* handles bounds */
8283 /* XXX: currently, since we do only one pass, we cannot track
8284 '&' operators, so we add only arrays */
8285 if (do_bounds_check
&& (type
->t
& VT_ARRAY
)) {
8286 unsigned long *bounds_ptr
;
8287 /* add padding between regions */
8289 /* then add local bound info */
8290 bounds_ptr
= section_ptr_add(lbounds_section
, 2 * sizeof(unsigned long));
8291 bounds_ptr
[0] = addr
;
8292 bounds_ptr
[1] = size
;
8295 /* local variable */
8296 sym_push(v
, type
, r
, addr
);
8298 /* push local reference */
8299 vset(type
, r
, addr
);
8305 if (v
&& scope
== VT_CONST
) {
8306 /* see if the symbol was already defined */
8309 if (!is_compatible_types(&sym
->type
, type
))
8310 error("incompatible types for redefinition of '%s'",
8311 get_tok_str(v
, NULL
));
8312 if (sym
->type
.t
& VT_EXTERN
) {
8313 /* if the variable is extern, it was not allocated */
8314 sym
->type
.t
&= ~VT_EXTERN
;
8316 /* we accept several definitions of the same
8317 global variable. this is tricky, because we
8318 must play with the SHN_COMMON type of the symbol */
8319 /* XXX: should check if the variable was already
8320 initialized. It is incorrect to initialized it
8322 /* no init data, we won't add more to the symbol */
8329 /* allocate symbol in corresponding section */
8336 data_offset
= sec
->data_offset
;
8337 data_offset
= (data_offset
+ align
- 1) & -align
;
8339 /* very important to increment global pointer at this time
8340 because initializers themselves can create new initializers */
8341 data_offset
+= size
;
8342 /* add padding if bound check */
8343 if (do_bounds_check
)
8345 sec
->data_offset
= data_offset
;
8346 /* allocate section space to put the data */
8347 if (sec
->sh_type
!= SHT_NOBITS
&&
8348 data_offset
> sec
->data_allocated
)
8349 section_realloc(sec
, data_offset
);
8351 addr
= 0; /* avoid warning */
8355 if (scope
== VT_CONST
) {
8360 sym
= sym_push(v
, type
, r
| VT_SYM
, 0);
8362 /* update symbol definition */
8364 put_extern_sym(sym
, sec
, addr
, size
);
8367 /* put a common area */
8368 put_extern_sym(sym
, NULL
, align
, size
);
8369 /* XXX: find a nicer way */
8370 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
8371 esym
->st_shndx
= SHN_COMMON
;
8376 /* push global reference */
8377 sym
= get_sym_ref(type
, sec
, addr
, size
);
8379 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
8383 /* handles bounds now because the symbol must be defined
8384 before for the relocation */
8385 if (do_bounds_check
) {
8386 unsigned long *bounds_ptr
;
8388 greloc(bounds_section
, sym
, bounds_section
->data_offset
, R_DATA_32
);
8389 /* then add global bound info */
8390 bounds_ptr
= section_ptr_add(bounds_section
, 2 * sizeof(long));
8391 bounds_ptr
[0] = 0; /* relocated */
8392 bounds_ptr
[1] = size
;
8396 decl_initializer(type
, sec
, addr
, 1, 0);
8397 /* restore parse state if needed */
8399 tok_str_free(init_str
.str
);
8400 restore_parse_state(&saved_parse_state
);
8406 void put_func_debug(Sym
*sym
)
8411 /* XXX: we put here a dummy type */
8412 snprintf(buf
, sizeof(buf
), "%s:%c1",
8413 funcname
, sym
->type
.t
& VT_STATIC
? 'f' : 'F');
8414 put_stabs_r(buf
, N_FUN
, 0, file
->line_num
, 0,
8415 cur_text_section
, sym
->c
);
8420 /* not finished : try to put some local vars in registers */
8421 //#define CONFIG_REG_VARS
8423 #ifdef CONFIG_REG_VARS
8424 void add_var_ref(int t
)
8426 printf("%s:%d: &%s\n",
8427 file
->filename
, file
->line_num
,
8428 get_tok_str(t
, NULL
));
8431 /* first pass on a function with heuristic to extract variable usage
8432 and pointer references to local variables for register allocation */
8433 void analyse_function(void)
8440 /* any symbol coming after '&' is considered as being a
8441 variable whose reference is taken. It is highly unaccurate
8442 but it is difficult to do better without a complete parse */
8445 /* if '& number', then no need to examine next tokens */
8446 if (tok
== TOK_CINT
||
8448 tok
== TOK_CLLONG
||
8449 tok
== TOK_CULLONG
) {
8451 } else if (tok
>= TOK_UIDENT
) {
8452 /* if '& ident [' or '& ident ->', then ident address
8456 if (tok
!= '[' && tok
!= TOK_ARROW
)
8460 while (tok
!= '}' && tok
!= ';' &&
8461 !((tok
== ',' || tok
== ')') && level
== 0)) {
8462 if (tok
>= TOK_UIDENT
) {
8464 } else if (tok
== '(') {
8466 } else if (tok
== ')') {
8479 /* parse an old style function declaration list */
8480 /* XXX: check multiple parameter */
8481 static void func_decl_list(Sym
*func_sym
)
8488 /* parse each declaration */
8489 while (tok
!= '{' && tok
!= ';' && tok
!= ',' && tok
!= TOK_EOF
) {
8490 if (!parse_btype(&btype
, &ad
))
8491 expect("declaration list");
8492 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
8493 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
8495 /* we accept no variable after */
8499 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
8500 /* find parameter in function parameter list */
8503 if ((s
->v
& ~SYM_FIELD
) == v
)
8507 error("declaration for parameter '%s' but no such parameter",
8508 get_tok_str(v
, NULL
));
8510 /* check that no storage specifier except 'register' was given */
8511 if (type
.t
& VT_STORAGE
)
8512 error("storage class specified for '%s'", get_tok_str(v
, NULL
));
8513 convert_parameter_type(&type
);
8514 /* we can add the type (NOTE: it could be local to the function) */
8516 /* accept other parameters */
8527 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8528 static void decl(int l
)
8536 if (!parse_btype(&btype
, &ad
)) {
8537 /* skip redundant ';' */
8538 /* XXX: find more elegant solution */
8543 /* special test for old K&R protos without explicit int
8544 type. Only accepted when defining global data */
8545 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
8549 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
8550 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
8552 /* we accept no variable after */
8556 while (1) { /* iterate thru each declaration */
8558 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
8562 type_to_str(buf
, sizeof(buf
), t
, get_tok_str(v
, NULL
));
8563 printf("type = '%s'\n", buf
);
8566 if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
8567 /* if old style function prototype, we accept a
8570 if (sym
->c
== FUNC_OLD
)
8571 func_decl_list(sym
);
8575 #ifdef CONFIG_REG_VARS
8576 TokenString func_str
;
8577 ParseState saved_parse_state
;
8582 error("cannot use local functions");
8583 if (!(type
.t
& VT_FUNC
))
8584 expect("function definition");
8586 /* reject abstract declarators in function definition */
8588 while ((sym
= sym
->next
) != NULL
)
8589 if (!(sym
->v
& ~SYM_FIELD
))
8590 expect("identifier");
8592 /* XXX: cannot do better now: convert extern line to static inline */
8593 if ((type
.t
& (VT_EXTERN
| VT_INLINE
)) == (VT_EXTERN
| VT_INLINE
))
8594 type
.t
= (type
.t
& ~VT_EXTERN
) | VT_STATIC
;
8596 #ifdef CONFIG_REG_VARS
8597 /* parse all function code and record it */
8599 tok_str_new(&func_str
);
8605 error("unexpected end of file");
8606 tok_str_add_tok(&func_str
);
8611 } else if (t
== '}') {
8613 if (block_level
== 0)
8617 tok_str_add(&func_str
, -1);
8618 tok_str_add(&func_str
, 0);
8620 save_parse_state(&saved_parse_state
);
8622 macro_ptr
= func_str
.str
;
8627 /* compute text section */
8628 cur_text_section
= ad
.section
;
8629 if (!cur_text_section
)
8630 cur_text_section
= text_section
;
8631 ind
= cur_text_section
->data_offset
;
8632 funcname
= get_tok_str(v
, NULL
);
8635 /* if symbol is already defined, then put complete type */
8638 /* put function symbol */
8639 sym
= global_identifier_push(v
, type
.t
, 0);
8640 sym
->type
.ref
= type
.ref
;
8642 /* NOTE: we patch the symbol size later */
8643 put_extern_sym(sym
, cur_text_section
, ind
, 0);
8645 sym
->r
= VT_SYM
| VT_CONST
;
8646 /* put debug symbol */
8648 put_func_debug(sym
);
8649 /* push a dummy symbol to enable local sym storage */
8650 sym_push2(&local_stack
, SYM_FIELD
, 0, 0);
8651 gfunc_prolog(&type
);
8654 #ifdef CONFIG_REG_VARS
8655 macro_ptr
= func_str
.str
;
8658 block(NULL
, NULL
, NULL
, NULL
, 0, 0);
8661 cur_text_section
->data_offset
= ind
;
8662 label_pop(&global_label_stack
, NULL
);
8663 sym_pop(&local_stack
, NULL
); /* reset local stack */
8664 /* end of function */
8665 /* patch symbol size */
8666 ((Elf32_Sym
*)symtab_section
->data
)[sym
->c
].st_size
=
8669 put_stabn(N_FUN
, 0, 0, ind
- func_ind
);
8671 funcname
= ""; /* for safety */
8672 func_vt
.t
= VT_VOID
; /* for safety */
8673 ind
= 0; /* for safety */
8675 #ifdef CONFIG_REG_VARS
8676 tok_str_free(func_str
.str
);
8677 restore_parse_state(&saved_parse_state
);
8681 if (btype
.t
& VT_TYPEDEF
) {
8682 /* save typedefed type */
8683 /* XXX: test storage specifiers ? */
8684 sym
= sym_push(v
, &type
, 0, 0);
8685 sym
->type
.t
|= VT_TYPEDEF
;
8686 } else if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
8687 /* external function definition */
8688 external_sym(v
, &type
, 0);
8690 /* not lvalue if array */
8692 if (!(type
.t
& VT_ARRAY
))
8693 r
|= lvalue_type(type
.t
);
8694 has_init
= (tok
== '=');
8695 if ((btype
.t
& VT_EXTERN
) ||
8696 ((type
.t
& VT_ARRAY
) && (type
.t
& VT_STATIC
) &&
8697 !has_init
&& l
== VT_CONST
&& type
.ref
->c
< 0)) {
8698 /* external variable */
8699 /* NOTE: as GCC, uninitialized global static
8700 arrays of null size are considered as
8702 external_sym(v
, &type
, r
);
8704 if (type
.t
& VT_STATIC
)
8710 decl_initializer_alloc(&type
, &ad
, r
,
8724 /* better than nothing, but needs extension to handle '-E' option
8726 static void preprocess_init(TCCState
*s1
)
8728 s1
->include_stack_ptr
= s1
->include_stack
;
8729 /* XXX: move that before to avoid having to initialize
8730 file->ifdef_stack_ptr ? */
8731 s1
->ifdef_stack_ptr
= s1
->ifdef_stack
;
8732 file
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
8734 /* XXX: not ANSI compliant: bound checking says error */
8738 /* compile the C file opened in 'file'. Return non zero if errors. */
8739 static int tcc_compile(TCCState
*s1
)
8743 volatile int section_sym
;
8746 printf("%s: **** new file\n", file
->filename
);
8748 preprocess_init(s1
);
8751 anon_sym
= SYM_FIRST_ANOM
;
8753 /* file info: full path + filename */
8754 section_sym
= 0; /* avoid warning */
8756 section_sym
= put_elf_sym(symtab_section
, 0, 0,
8757 ELF32_ST_INFO(STB_LOCAL
, STT_SECTION
), 0,
8758 text_section
->sh_num
, NULL
);
8759 getcwd(buf
, sizeof(buf
));
8760 pstrcat(buf
, sizeof(buf
), "/");
8761 put_stabs_r(buf
, N_SO
, 0, 0,
8762 text_section
->data_offset
, text_section
, section_sym
);
8763 put_stabs_r(file
->filename
, N_SO
, 0, 0,
8764 text_section
->data_offset
, text_section
, section_sym
);
8766 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
8767 symbols can be safely used */
8768 put_elf_sym(symtab_section
, 0, 0,
8769 ELF32_ST_INFO(STB_LOCAL
, STT_FILE
), 0,
8770 SHN_ABS
, file
->filename
);
8772 /* define some often used types */
8773 int_type
.t
= VT_INT
;
8775 char_pointer_type
.t
= VT_BYTE
;
8776 mk_pointer(&char_pointer_type
);
8778 func_old_type
.t
= VT_FUNC
;
8779 func_old_type
.ref
= sym_push(SYM_FIELD
, &int_type
, FUNC_CDECL
, FUNC_OLD
);
8782 /* define 'void *alloca(unsigned int)' builtin function */
8787 sym
= sym_push(p
, mk_pointer(VT_VOID
), FUNC_CDECL
, FUNC_NEW
);
8788 s1
= sym_push(SYM_FIELD
, VT_UNSIGNED
| VT_INT
, 0, 0);
8791 sym_push(TOK_alloca
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), VT_CONST
, 0);
8795 define_start
= define_stack
;
8797 if (setjmp(s1
->error_jmp_buf
) == 0) {
8799 s1
->error_set_jmp_enabled
= 1;
8801 ch
= file
->buf_ptr
[0];
8802 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
8803 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
;
8807 expect("declaration");
8809 /* end of translation unit info */
8811 put_stabs_r(NULL
, N_SO
, 0, 0,
8812 text_section
->data_offset
, text_section
, section_sym
);
8815 s1
->error_set_jmp_enabled
= 0;
8817 /* reset define stack, but leave -Dsymbols (may be incorrect if
8818 they are undefined) */
8819 free_defines(define_start
);
8821 sym_pop(&global_stack
, NULL
);
8823 return s1
->nb_errors
!= 0 ? -1 : 0;
8827 int tcc_compile_string(TCCState
*s
, const char *str
)
8829 BufferedFile bf1
, *bf
= &bf1
;
8833 /* init file structure */
8835 /* XXX: avoid copying */
8837 buf
= tcc_malloc(len
+ 1);
8840 memcpy(buf
, str
, len
);
8843 bf
->buf_end
= buf
+ len
;
8844 pstrcpy(bf
->filename
, sizeof(bf
->filename
), "<string>");
8848 ret
= tcc_compile(s
);
8852 /* currently, no need to close */
8857 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
8858 void tcc_define_symbol(TCCState
*s1
, const char *sym
, const char *value
)
8860 BufferedFile bf1
, *bf
= &bf1
;
8862 pstrcpy(bf
->buffer
, IO_BUF_SIZE
, sym
);
8863 pstrcat(bf
->buffer
, IO_BUF_SIZE
, " ");
8867 pstrcat(bf
->buffer
, IO_BUF_SIZE
, value
);
8869 /* init file structure */
8871 bf
->buf_ptr
= bf
->buffer
;
8872 bf
->buf_end
= bf
->buffer
+ strlen(bf
->buffer
);
8873 *bf
->buf_end
= CH_EOB
;
8874 bf
->filename
[0] = '\0';
8878 s1
->include_stack_ptr
= s1
->include_stack
;
8880 /* parse with define parser */
8881 ch
= file
->buf_ptr
[0];
8887 /* undefine a preprocessor symbol */
8888 void tcc_undefine_symbol(TCCState
*s1
, const char *sym
)
8892 ts
= tok_alloc(sym
, strlen(sym
));
8893 s
= define_find(ts
->tok
);
8894 /* undefine symbol by putting an invalid name */
8899 #ifdef CONFIG_TCC_ASM
8901 #ifdef TCC_TARGET_I386
8902 #include "i386-asm.c"
8907 static void asm_instr(void)
8909 error("inline asm() not supported");
8915 /* print the position in the source file of PC value 'pc' by reading
8916 the stabs debug information */
8917 static void rt_printline(unsigned long wanted_pc
)
8919 Stab_Sym
*sym
, *sym_end
;
8920 char func_name
[128], last_func_name
[128];
8921 unsigned long func_addr
, last_pc
, pc
;
8922 const char *incl_files
[INCLUDE_STACK_SIZE
];
8923 int incl_index
, len
, last_line_num
, i
;
8924 const char *str
, *p
;
8926 fprintf(stderr
, "0x%08lx:", wanted_pc
);
8928 func_name
[0] = '\0';
8931 last_func_name
[0] = '\0';
8932 last_pc
= 0xffffffff;
8934 sym
= (Stab_Sym
*)stab_section
->data
+ 1;
8935 sym_end
= (Stab_Sym
*)(stab_section
->data
+ stab_section
->data_offset
);
8936 while (sym
< sym_end
) {
8937 switch(sym
->n_type
) {
8938 /* function start or end */
8940 if (sym
->n_strx
== 0) {
8941 /* we test if between last line and end of function */
8942 pc
= sym
->n_value
+ func_addr
;
8943 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
8945 func_name
[0] = '\0';
8948 str
= stabstr_section
->data
+ sym
->n_strx
;
8949 p
= strchr(str
, ':');
8951 pstrcpy(func_name
, sizeof(func_name
), str
);
8954 if (len
> sizeof(func_name
) - 1)
8955 len
= sizeof(func_name
) - 1;
8956 memcpy(func_name
, str
, len
);
8957 func_name
[len
] = '\0';
8959 func_addr
= sym
->n_value
;
8962 /* line number info */
8964 pc
= sym
->n_value
+ func_addr
;
8965 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
8968 last_line_num
= sym
->n_desc
;
8970 strcpy(last_func_name
, func_name
);
8974 str
= stabstr_section
->data
+ sym
->n_strx
;
8976 if (incl_index
< INCLUDE_STACK_SIZE
) {
8977 incl_files
[incl_index
++] = str
;
8985 if (sym
->n_strx
== 0) {
8986 incl_index
= 0; /* end of translation unit */
8988 str
= stabstr_section
->data
+ sym
->n_strx
;
8989 /* do not add path */
8991 if (len
> 0 && str
[len
- 1] != '/')
8999 /* second pass: we try symtab symbols (no line number info) */
9002 Elf32_Sym
*sym
, *sym_end
;
9005 sym_end
= (Elf32_Sym
*)(symtab_section
->data
+ symtab_section
->data_offset
);
9006 for(sym
= (Elf32_Sym
*)symtab_section
->data
+ 1;
9009 type
= ELF32_ST_TYPE(sym
->st_info
);
9010 if (type
== STT_FUNC
) {
9011 if (wanted_pc
>= sym
->st_value
&&
9012 wanted_pc
< sym
->st_value
+ sym
->st_size
) {
9013 pstrcpy(last_func_name
, sizeof(last_func_name
),
9014 strtab_section
->data
+ sym
->st_name
);
9020 /* did not find any info: */
9021 fprintf(stderr
, " ???\n");
9024 if (last_func_name
[0] != '\0') {
9025 fprintf(stderr
, " %s()", last_func_name
);
9027 if (incl_index
> 0) {
9028 fprintf(stderr
, " (%s:%d",
9029 incl_files
[incl_index
- 1], last_line_num
);
9030 for(i
= incl_index
- 2; i
>= 0; i
--)
9031 fprintf(stderr
, ", included from %s", incl_files
[i
]);
9032 fprintf(stderr
, ")");
9034 fprintf(stderr
, "\n");
9041 /* fix for glibc 2.1 */
9047 /* return the PC at frame level 'level'. Return non zero if not found */
9048 static int rt_get_caller_pc(unsigned long *paddr
,
9049 ucontext_t
*uc
, int level
)
9056 *paddr
= uc
->uc_mcontext
.mc_eip
;
9058 *paddr
= uc
->uc_mcontext
.gregs
[REG_EIP
];
9063 fp
= uc
->uc_mcontext
.mc_ebp
;
9065 fp
= uc
->uc_mcontext
.gregs
[REG_EBP
];
9067 for(i
=1;i
<level
;i
++) {
9068 /* XXX: check address validity with program info */
9069 if (fp
<= 0x1000 || fp
>= 0xc0000000)
9071 fp
= ((unsigned long *)fp
)[0];
9073 *paddr
= ((unsigned long *)fp
)[1];
9079 #warning add arch specific rt_get_caller_pc()
9081 static int rt_get_caller_pc(unsigned long *paddr
,
9082 ucontext_t
*uc
, int level
)
9088 /* emit a run time error at position 'pc' */
9089 void rt_error(ucontext_t
*uc
, const char *fmt
, ...)
9096 fprintf(stderr
, "Runtime error: ");
9097 vfprintf(stderr
, fmt
, ap
);
9098 fprintf(stderr
, "\n");
9099 for(i
=0;i
<num_callers
;i
++) {
9100 if (rt_get_caller_pc(&pc
, uc
, i
) < 0)
9103 fprintf(stderr
, "at ");
9105 fprintf(stderr
, "by ");
9112 /* signal handler for fatal errors */
9113 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
9115 ucontext_t
*uc
= puc
;
9119 switch(siginf
->si_code
) {
9122 rt_error(uc
, "division by zero");
9125 rt_error(uc
, "floating point exception");
9131 if (rt_bound_error_msg
&& *rt_bound_error_msg
)
9132 rt_error(uc
, *rt_bound_error_msg
);
9134 rt_error(uc
, "dereferencing invalid pointer");
9137 rt_error(uc
, "illegal instruction");
9140 rt_error(uc
, "abort() called");
9143 rt_error(uc
, "caught signal %d", signum
);
9150 /* do all relocations (needed before using tcc_get_symbol()) */
9151 int tcc_relocate(TCCState
*s1
)
9158 tcc_add_runtime(s1
);
9160 build_got_entries(s1
);
9162 relocate_common_syms();
9164 /* compute relocation address : section are relocated in place. We
9165 also alloc the bss space */
9166 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9167 s
= s1
->sections
[i
];
9168 if (s
->sh_flags
& SHF_ALLOC
) {
9169 if (s
->sh_type
== SHT_NOBITS
)
9170 s
->data
= tcc_mallocz(s
->data_offset
);
9171 s
->sh_addr
= (unsigned long)s
->data
;
9175 relocate_syms(s1
, 1);
9177 if (s1
->nb_errors
!= 0)
9180 /* relocate each section */
9181 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9182 s
= s1
->sections
[i
];
9184 relocate_section(s1
, s
);
9189 /* launch the compiled program with the given arguments */
9190 int tcc_run(TCCState
*s1
, int argc
, char **argv
)
9192 int (*prog_main
)(int, char **);
9194 if (tcc_relocate(s1
) < 0)
9197 prog_main
= tcc_get_symbol_err(s1
, "main");
9201 error("debug mode currently not available for Windows");
9203 struct sigaction sigact
;
9204 /* install TCC signal handlers to print debug info on fatal
9206 sigact
.sa_flags
= SA_SIGINFO
| SA_RESETHAND
;
9207 sigact
.sa_sigaction
= sig_error
;
9208 sigemptyset(&sigact
.sa_mask
);
9209 sigaction(SIGFPE
, &sigact
, NULL
);
9210 sigaction(SIGILL
, &sigact
, NULL
);
9211 sigaction(SIGSEGV
, &sigact
, NULL
);
9212 sigaction(SIGBUS
, &sigact
, NULL
);
9213 sigaction(SIGABRT
, &sigact
, NULL
);
9217 #ifdef CONFIG_TCC_BCHECK
9218 if (do_bounds_check
) {
9219 void (*bound_init
)(void);
9221 /* set error function */
9222 rt_bound_error_msg
= (void *)tcc_get_symbol_err(s1
,
9223 "__bound_error_msg");
9225 /* XXX: use .init section so that it also work in binary ? */
9226 bound_init
= (void *)tcc_get_symbol_err(s1
, "__bound_init");
9230 return (*prog_main
)(argc
, argv
);
9233 TCCState
*tcc_new(void)
9240 s
= tcc_mallocz(sizeof(TCCState
));
9244 s
->output_type
= TCC_OUTPUT_MEMORY
;
9246 /* init isid table */
9248 isidnum_table
[i
] = isid(i
) || isnum(i
);
9250 /* add all tokens */
9252 memset(hash_ident
, 0, TOK_HASH_SIZE
* sizeof(TokenSym
*));
9254 tok_ident
= TOK_IDENT
;
9263 ts
= tok_alloc(p
, r
- p
- 1);
9267 /* we add dummy defines for some special macros to speed up tests
9268 and to have working defined() */
9269 define_push(TOK___LINE__
, MACRO_OBJ
, NULL
, NULL
);
9270 define_push(TOK___FILE__
, MACRO_OBJ
, NULL
, NULL
);
9271 define_push(TOK___DATE__
, MACRO_OBJ
, NULL
, NULL
);
9272 define_push(TOK___TIME__
, MACRO_OBJ
, NULL
, NULL
);
9274 /* standard defines */
9275 tcc_define_symbol(s
, "__STDC__", NULL
);
9276 #if defined(TCC_TARGET_I386)
9277 tcc_define_symbol(s
, "__i386__", NULL
);
9279 #if defined(TCC_TARGET_ARM)
9280 tcc_define_symbol(s
, "__ARM_ARCH_4__", NULL
);
9281 tcc_define_symbol(s
, "__arm_elf__", NULL
);
9282 tcc_define_symbol(s
, "__arm_elf", NULL
);
9283 tcc_define_symbol(s
, "arm_elf", NULL
);
9284 tcc_define_symbol(s
, "__arm__", NULL
);
9285 tcc_define_symbol(s
, "__arm", NULL
);
9286 tcc_define_symbol(s
, "arm", NULL
);
9287 tcc_define_symbol(s
, "__APCS_32__", NULL
);
9289 #ifdef CHAR_IS_UNSIGNED
9290 tcc_define_symbol(s
, "__CHAR_UNSIGNED__", NULL
);
9293 tcc_define_symbol(s
, "__linux__", NULL
);
9294 tcc_define_symbol(s
, "linux", NULL
);
9296 /* tiny C specific defines */
9297 tcc_define_symbol(s
, "__TINYC__", NULL
);
9299 /* tiny C & gcc defines */
9300 tcc_define_symbol(s
, "__SIZE_TYPE__", "unsigned int");
9301 tcc_define_symbol(s
, "__PTRDIFF_TYPE__", "int");
9302 tcc_define_symbol(s
, "__WCHAR_TYPE__", "int");
9304 /* default library paths */
9305 tcc_add_library_path(s
, "/usr/local/lib");
9306 tcc_add_library_path(s
, "/usr/lib");
9307 tcc_add_library_path(s
, "/lib");
9309 /* no section zero */
9310 dynarray_add((void ***)&s
->sections
, &s
->nb_sections
, NULL
);
9312 /* create standard sections */
9313 text_section
= new_section(s
, ".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
9314 data_section
= new_section(s
, ".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
9315 bss_section
= new_section(s
, ".bss", SHT_NOBITS
, SHF_ALLOC
| SHF_WRITE
);
9317 /* symbols are always generated for linking stage */
9318 symtab_section
= new_symtab(s
, ".symtab", SHT_SYMTAB
, 0,
9320 ".hashtab", SHF_PRIVATE
);
9321 strtab_section
= symtab_section
->link
;
9323 /* private symbol table for dynamic symbols */
9324 s
->dynsymtab_section
= new_symtab(s
, ".dynsymtab", SHT_SYMTAB
, SHF_PRIVATE
,
9326 ".dynhashtab", SHF_PRIVATE
);
9327 s
->alacarte_link
= 1;
9331 void tcc_delete(TCCState
*s1
)
9335 /* free -D defines */
9339 n
= tok_ident
- TOK_IDENT
;
9340 for(i
= 0; i
< n
; i
++)
9341 tcc_free(table_ident
[i
]);
9342 tcc_free(table_ident
);
9344 /* free all sections */
9346 free_section(symtab_section
->hash
);
9348 free_section(s1
->dynsymtab_section
->hash
);
9349 free_section(s1
->dynsymtab_section
->link
);
9350 free_section(s1
->dynsymtab_section
);
9352 for(i
= 1; i
< s1
->nb_sections
; i
++)
9353 free_section(s1
->sections
[i
]);
9354 tcc_free(s1
->sections
);
9356 /* free loaded dlls array */
9357 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++)
9358 tcc_free(s1
->loaded_dlls
[i
]);
9359 tcc_free(s1
->loaded_dlls
);
9362 for(i
= 0; i
< s1
->nb_library_paths
; i
++)
9363 tcc_free(s1
->library_paths
[i
]);
9364 tcc_free(s1
->library_paths
);
9366 /* cached includes */
9367 for(i
= 0; i
< s1
->nb_cached_includes
; i
++)
9368 tcc_free(s1
->cached_includes
[i
]);
9369 tcc_free(s1
->cached_includes
);
9371 for(i
= 0; i
< s1
->nb_include_paths
; i
++)
9372 tcc_free(s1
->include_paths
[i
]);
9373 tcc_free(s1
->include_paths
);
9375 for(i
= 0; i
< s1
->nb_sysinclude_paths
; i
++)
9376 tcc_free(s1
->sysinclude_paths
[i
]);
9377 tcc_free(s1
->sysinclude_paths
);
9382 int tcc_add_include_path(TCCState
*s1
, const char *pathname
)
9386 pathname1
= tcc_strdup(pathname
);
9387 dynarray_add((void ***)&s1
->include_paths
, &s1
->nb_include_paths
, pathname1
);
9391 int tcc_add_sysinclude_path(TCCState
*s1
, const char *pathname
)
9395 pathname1
= tcc_strdup(pathname
);
9396 dynarray_add((void ***)&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
, pathname1
);
9400 static int tcc_add_file_internal(TCCState
*s1
, const char *filename
, int flags
)
9402 const char *ext
, *filename1
;
9405 BufferedFile
*saved_file
;
9407 /* find source file type with extension */
9408 filename1
= strrchr(filename
, '/');
9412 filename1
= filename
;
9413 ext
= strrchr(filename1
, '.');
9419 file
= tcc_open(s1
, filename
);
9421 if (flags
& AFF_PRINT_ERROR
) {
9422 error_noabort("file '%s' not found", filename
);
9428 if (!ext
|| !strcmp(ext
, "c")) {
9429 /* C file assumed */
9430 ret
= tcc_compile(s1
);
9432 #ifdef CONFIG_TCC_ASM
9433 if (!strcmp(ext
, "S")) {
9434 /* preprocessed assembler */
9435 ret
= tcc_assemble(s1
, 1);
9436 } else if (!strcmp(ext
, "s")) {
9437 /* non preprocessed assembler */
9438 ret
= tcc_assemble(s1
, 0);
9443 /* assume executable format: auto guess file type */
9444 ret
= read(fd
, &ehdr
, sizeof(ehdr
));
9445 lseek(fd
, 0, SEEK_SET
);
9447 error_noabort("could not read header");
9449 } else if (ret
!= sizeof(ehdr
)) {
9450 goto try_load_script
;
9453 if (ehdr
.e_ident
[0] == ELFMAG0
&&
9454 ehdr
.e_ident
[1] == ELFMAG1
&&
9455 ehdr
.e_ident
[2] == ELFMAG2
&&
9456 ehdr
.e_ident
[3] == ELFMAG3
) {
9457 file
->line_num
= 0; /* do not display line number if error */
9458 if (ehdr
.e_type
== ET_REL
) {
9459 ret
= tcc_load_object_file(s1
, fd
, 0);
9460 } else if (ehdr
.e_type
== ET_DYN
) {
9461 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
9463 h
= dlopen(filename
, RTLD_GLOBAL
| RTLD_LAZY
);
9469 ret
= tcc_load_dll(s1
, fd
, filename
,
9470 (flags
& AFF_REFERENCED_DLL
) != 0);
9473 error_noabort("unrecognized ELF file");
9476 } else if (memcmp((char *)&ehdr
, ARMAG
, 8) == 0) {
9477 file
->line_num
= 0; /* do not display line number if error */
9478 ret
= tcc_load_archive(s1
, fd
);
9480 /* as GNU ld, consider it is an ld script if not recognized */
9482 ret
= tcc_load_ldscript(s1
);
9484 error_noabort("unrecognized file type");
9499 int tcc_add_file(TCCState
*s
, const char *filename
)
9501 return tcc_add_file_internal(s
, filename
, AFF_PRINT_ERROR
);
9504 int tcc_add_library_path(TCCState
*s
, const char *pathname
)
9508 pathname1
= tcc_strdup(pathname
);
9509 dynarray_add((void ***)&s
->library_paths
, &s
->nb_library_paths
, pathname1
);
9513 /* find and load a dll. Return non zero if not found */
9514 /* XXX: add '-rpath' option support ? */
9515 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
)
9520 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
9521 snprintf(buf
, sizeof(buf
), "%s/%s",
9522 s
->library_paths
[i
], filename
);
9523 if (tcc_add_file_internal(s
, buf
, flags
) == 0)
9529 /* the library name is the same as the argument of the '-l' option */
9530 int tcc_add_library(TCCState
*s
, const char *libraryname
)
9535 /* first we look for the dynamic library if not static linking */
9536 if (!s
->static_link
) {
9537 snprintf(buf
, sizeof(buf
), "lib%s.so", libraryname
);
9538 if (tcc_add_dll(s
, buf
, 0) == 0)
9542 /* then we look for the static library */
9543 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
9544 snprintf(buf
, sizeof(buf
), "%s/lib%s.a",
9545 s
->library_paths
[i
], libraryname
);
9546 if (tcc_add_file_internal(s
, buf
, 0) == 0)
9552 int tcc_add_symbol(TCCState
*s
, const char *name
, unsigned long val
)
9554 add_elf_sym(symtab_section
, val
, 0,
9555 ELF32_ST_INFO(STB_GLOBAL
, STT_NOTYPE
),
9560 int tcc_set_output_type(TCCState
*s
, int output_type
)
9564 s
->output_type
= output_type
;
9567 /* default include paths */
9568 /* XXX: reverse order needed if -isystem support */
9569 tcc_add_sysinclude_path(s
, "/usr/local/include");
9570 tcc_add_sysinclude_path(s
, "/usr/include");
9571 snprintf(buf
, sizeof(buf
), "%s/include", tcc_lib_path
);
9572 tcc_add_sysinclude_path(s
, buf
);
9575 /* if bound checking, then add corresponding sections */
9576 #ifdef CONFIG_TCC_BCHECK
9577 if (do_bounds_check
) {
9579 tcc_define_symbol(s
, "__BOUNDS_CHECKING_ON", NULL
);
9580 /* create bounds sections */
9581 bounds_section
= new_section(s
, ".bounds",
9582 SHT_PROGBITS
, SHF_ALLOC
);
9583 lbounds_section
= new_section(s
, ".lbounds",
9584 SHT_PROGBITS
, SHF_ALLOC
);
9588 /* add debug sections */
9591 stab_section
= new_section(s
, ".stab", SHT_PROGBITS
, 0);
9592 stab_section
->sh_entsize
= sizeof(Stab_Sym
);
9593 stabstr_section
= new_section(s
, ".stabstr", SHT_STRTAB
, 0);
9594 put_elf_str(stabstr_section
, "");
9595 stab_section
->link
= stabstr_section
;
9596 /* put first entry */
9597 put_stabs("", 0, 0, 0, 0);
9600 /* add libc crt1/crti objects */
9601 if ((output_type
== TCC_OUTPUT_EXE
|| output_type
== TCC_OUTPUT_DLL
) &&
9603 if (output_type
!= TCC_OUTPUT_DLL
)
9604 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crt1.o");
9605 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crti.o");
9610 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
9612 typedef struct WarningDef
{
9618 static const WarningDef warning_defs
[] = {
9619 { offsetof(TCCState
, warn_unsupported
), 0, "unsupported" },
9620 { offsetof(TCCState
, warn_write_strings
), 0, "write-strings" },
9621 { offsetof(TCCState
, warn_error
), 0, "error" },
9624 /* set/reset a warning */
9625 int tcc_set_warning(TCCState
*s
, const char *warning_name
, int value
)
9628 const WarningDef
*p
;
9629 if (!strcmp(warning_name
, "all")) {
9630 for(i
= 0, p
= warning_defs
; i
< countof(warning_defs
); i
++, p
++) {
9631 if (p
->flags
& WD_ALL
)
9632 *(int *)((uint8_t *)s
+ p
->offset
) = 1;
9635 for(i
= 0, p
= warning_defs
; i
< countof(warning_defs
); i
++, p
++) {
9636 if (!strcmp(warning_name
, p
->name
))
9641 *(int *)((uint8_t *)s
+ p
->offset
) = value
;
9646 #if !defined(LIBTCC)
9648 /* extract the basename of a file */
9649 static const char *tcc_basename(const char *name
)
9652 p
= strrchr(name
, '/');
9655 p
= strrchr(name
, '\\');
9664 static int64_t getclock_us(void)
9669 return (tb
.time
* 1000LL + tb
.millitm
) * 1000LL;
9672 gettimeofday(&tv
, NULL
);
9673 return tv
.tv_sec
* 1000000LL + tv
.tv_usec
;
9679 printf("tcc version " TCC_VERSION
" - Tiny C Compiler - Copyright (C) 2001-2003 Fabrice Bellard\n"
9680 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
9681 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
9682 " [infile1 infile2...] [-run infile args...]\n"
9684 "General options:\n"
9685 " -v display current version\n"
9686 " -c compile only - generate an object file\n"
9687 " -o outfile set output filename\n"
9688 " -Bdir set tcc internal library path\n"
9689 " -bench output compilation statistics\n"
9690 " -run run compiled source\n"
9691 " -Wwarning set or reset (with 'no-' prefix) 'warning'\n"
9692 " -w disable all warnings\n"
9693 "Preprocessor options:\n"
9694 " -Idir add include path 'dir'\n"
9695 " -Dsym[=val] define 'sym' with value 'val'\n"
9696 " -Usym undefine 'sym'\n"
9698 " -Ldir add library path 'dir'\n"
9699 " -llib link with dynamic or static library 'lib'\n"
9700 " -shared generate a shared library\n"
9701 " -static static linking\n"
9702 " -rdynamic export all global symbols to dynamic linker\n"
9703 " -r relocatable output\n"
9704 "Debugger options:\n"
9705 " -g generate runtime debug info\n"
9706 #ifdef CONFIG_TCC_BCHECK
9707 " -b compile with built-in memory and bounds checker (implies -g)\n"
9709 " -bt N show N callers in stack traces\n"
9713 #define TCC_OPTION_HAS_ARG 0x0001
9714 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
9716 typedef struct TCCOption
{
9743 TCC_OPTION_nostdinc
,
9744 TCC_OPTION_nostdlib
,
9745 TCC_OPTION_print_search_dirs
,
9746 TCC_OPTION_rdynamic
,
9752 static const TCCOption tcc_options
[] = {
9753 { "h", TCC_OPTION_HELP
, 0 },
9754 { "?", TCC_OPTION_HELP
, 0 },
9755 { "I", TCC_OPTION_I
, TCC_OPTION_HAS_ARG
},
9756 { "D", TCC_OPTION_D
, TCC_OPTION_HAS_ARG
},
9757 { "U", TCC_OPTION_U
, TCC_OPTION_HAS_ARG
},
9758 { "L", TCC_OPTION_L
, TCC_OPTION_HAS_ARG
},
9759 { "B", TCC_OPTION_B
, TCC_OPTION_HAS_ARG
},
9760 { "l", TCC_OPTION_l
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
9761 { "bench", TCC_OPTION_bench
, 0 },
9762 { "bt", TCC_OPTION_bt
, TCC_OPTION_HAS_ARG
},
9763 #ifdef CONFIG_TCC_BCHECK
9764 { "b", TCC_OPTION_b
, 0 },
9766 { "g", TCC_OPTION_g
, 0 },
9767 { "c", TCC_OPTION_c
, 0 },
9768 { "static", TCC_OPTION_static
, 0 },
9769 { "shared", TCC_OPTION_shared
, 0 },
9770 { "o", TCC_OPTION_o
, TCC_OPTION_HAS_ARG
},
9771 { "run", TCC_OPTION_run
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
9772 { "rdynamic", TCC_OPTION_rdynamic
, 0 },
9773 { "r", TCC_OPTION_r
, 0 },
9774 { "W", TCC_OPTION_W
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
9775 { "O", TCC_OPTION_O
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
9776 { "m", TCC_OPTION_m
, TCC_OPTION_HAS_ARG
},
9777 { "f", TCC_OPTION_f
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
9778 { "nostdinc", TCC_OPTION_nostdinc
, 0 },
9779 { "nostdlib", TCC_OPTION_nostdlib
, 0 },
9780 { "print-search-dirs", TCC_OPTION_print_search_dirs
, 0 },
9781 { "v", TCC_OPTION_v
, 0 },
9782 { "w", TCC_OPTION_w
, 0 },
9786 /* convert 'str' into an array of space separated strings */
9787 static int expand_args(char ***pargv
, const char *str
)
9796 while (is_space(*str
))
9801 while (*str
!= '\0' && !is_space(*str
))
9804 arg
= tcc_malloc(len
+ 1);
9805 memcpy(arg
, s1
, len
);
9807 dynarray_add((void ***)&argv
, &argc
, arg
);
9813 static char **files
;
9814 static int nb_files
, nb_libraries
;
9815 static int multiple_files
;
9816 static int print_search_dirs
;
9817 static int output_type
;
9818 static int reloc_output
;
9819 static const char *outfile
;
9821 int parse_args(TCCState
*s
, int argc
, char **argv
)
9824 const TCCOption
*popt
;
9825 const char *optarg
, *p1
, *r1
;
9830 if (optind
>= argc
) {
9831 if (nb_files
== 0 && !print_search_dirs
)
9838 /* add a new file */
9839 dynarray_add((void ***)&files
, &nb_files
, r
);
9840 if (!multiple_files
) {
9842 /* argv[0] will be this file */
9846 /* find option in table (match only the first chars */
9851 error("invalid option -- '%s'", r
);
9864 if (popt
->flags
& TCC_OPTION_HAS_ARG
) {
9865 if (*r1
!= '\0' || (popt
->flags
& TCC_OPTION_NOSEP
)) {
9869 error("argument to '%s' is missing", r
);
9870 optarg
= argv
[optind
++];
9878 switch(popt
->index
) {
9879 case TCC_OPTION_HELP
:
9884 if (tcc_add_include_path(s
, optarg
) < 0)
9885 error("too many include paths");
9890 sym
= (char *)optarg
;
9891 value
= strchr(sym
, '=');
9896 tcc_define_symbol(s
, sym
, value
);
9900 tcc_undefine_symbol(s
, optarg
);
9903 tcc_add_library_path(s
, optarg
);
9906 /* set tcc utilities path (mainly for tcc development) */
9907 tcc_lib_path
= optarg
;
9910 dynarray_add((void ***)&files
, &nb_files
, r
);
9913 case TCC_OPTION_bench
:
9917 num_callers
= atoi(optarg
);
9919 #ifdef CONFIG_TCC_BCHECK
9921 do_bounds_check
= 1;
9930 output_type
= TCC_OUTPUT_OBJ
;
9932 case TCC_OPTION_static
:
9935 case TCC_OPTION_shared
:
9936 output_type
= TCC_OUTPUT_DLL
;
9943 /* generate a .o merging several output files */
9945 output_type
= TCC_OUTPUT_OBJ
;
9947 case TCC_OPTION_nostdinc
:
9950 case TCC_OPTION_nostdlib
:
9953 case TCC_OPTION_print_search_dirs
:
9954 print_search_dirs
= 1;
9956 case TCC_OPTION_run
:
9960 argc1
= expand_args(&argv1
, optarg
);
9962 parse_args(s
, argc1
, argv1
);
9965 output_type
= TCC_OUTPUT_MEMORY
;
9969 printf("tcc version %s\n", TCC_VERSION
);
9973 const char *p
= optarg
;
9976 if (p
[0] == 'n' && p
[1] == 'o' && p
[2] == '-') {
9980 if (tcc_set_warning(s
, p
, value
) < 0 && s
->warn_unsupported
)
9981 goto unsupported_option
;
9987 case TCC_OPTION_rdynamic
:
9991 if (s
->warn_unsupported
) {
9993 warning("unsupported option '%s'", r
);
10002 int main(int argc
, char **argv
)
10006 int nb_objfiles
, ret
, optind
;
10007 char objfilename
[1024];
10008 int64_t start_time
= 0;
10011 output_type
= TCC_OUTPUT_EXE
;
10013 multiple_files
= 1;
10018 print_search_dirs
= 0;
10020 optind
= parse_args(s
, argc
- 1, argv
+ 1) + 1;
10022 if (print_search_dirs
) {
10023 /* enough for Linux kernel */
10024 printf("install: %s/\n", tcc_lib_path
);
10028 nb_objfiles
= nb_files
- nb_libraries
;
10030 /* if outfile provided without other options, we output an
10032 if (outfile
&& output_type
== TCC_OUTPUT_MEMORY
)
10033 output_type
= TCC_OUTPUT_EXE
;
10035 /* check -c consistency : only single file handled. XXX: checks file type */
10036 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
10037 /* accepts only a single input file */
10038 if (nb_objfiles
!= 1)
10039 error("cannot specify multiple files with -c");
10040 if (nb_libraries
!= 0)
10041 error("cannot specify libraries with -c");
10044 /* compute default outfile name */
10045 if (output_type
!= TCC_OUTPUT_MEMORY
&& !outfile
) {
10046 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
10049 pstrcpy(objfilename
, sizeof(objfilename
) - 1,
10050 tcc_basename(files
[0]));
10051 /* add .o extension */
10052 ext
= strrchr(objfilename
, '.');
10054 goto default_outfile
;
10055 strcpy(ext
+ 1, "o");
10058 pstrcpy(objfilename
, sizeof(objfilename
), "a.out");
10060 outfile
= objfilename
;
10064 start_time
= getclock_us();
10067 tcc_set_output_type(s
, output_type
);
10069 /* compile or add each files or library */
10070 for(i
= 0;i
< nb_files
; i
++) {
10071 const char *filename
;
10073 filename
= files
[i
];
10074 if (filename
[0] == '-') {
10075 if (tcc_add_library(s
, filename
+ 2) < 0)
10076 error("cannot find %s", filename
);
10078 if (tcc_add_file(s
, filename
) < 0) {
10085 /* free all files */
10090 total_time
= (double)(getclock_us() - start_time
) / 1000000.0;
10091 if (total_time
< 0.001)
10092 total_time
= 0.001;
10093 if (total_bytes
< 1)
10095 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10096 tok_ident
- TOK_IDENT
, total_lines
, total_bytes
,
10097 total_time
, (int)(total_lines
/ total_time
),
10098 total_bytes
/ total_time
/ 1000000.0);
10101 if (s
->output_type
!= TCC_OUTPUT_MEMORY
) {
10102 tcc_output_file(s
, outfile
);
10105 ret
= tcc_run(s
, argc
- optind
, argv
+ optind
);
10108 /* XXX: cannot do it with bound checking because of the malloc hooks */
10109 if (!do_bounds_check
)
10114 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size
, mem_max_size
);