2 * TCC - Tiny C Compiler
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #define CONFIG_TCC_STATIC
43 #include <sys/timeb.h>
44 #define CONFIG_TCC_STATIC
48 #include <sys/ucontext.h>
51 #endif /* !CONFIG_TCCBOOT */
55 #ifndef CONFIG_TCC_STATIC
66 /* preprocessor debug */
68 /* include file debug */
76 /* target selection */
77 //#define TCC_TARGET_I386 /* i386 code generator */
78 //#define TCC_TARGET_ARM /* ARMv4 code generator */
79 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
81 /* default target is I386 */
82 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
83 !defined(TCC_TARGET_C67)
84 #define TCC_TARGET_I386
87 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
88 !defined(TCC_TARGET_C67)
89 #define CONFIG_TCC_BCHECK /* enable bound checking code */
92 /* define it to include assembler support */
93 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
94 #define CONFIG_TCC_ASM
97 /* object format selection */
98 #if defined(TCC_TARGET_C67)
99 #define TCC_TARGET_COFF
108 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
109 executables or dlls */
110 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
112 #define INCLUDE_STACK_SIZE 32
113 #define IFDEF_STACK_SIZE 64
114 #define VSTACK_SIZE 256
115 #define STRING_MAX_SIZE 1024
117 #define TOK_HASH_SIZE 8192 /* must be a power of two */
118 #define TOK_ALLOC_INCR 512 /* must be a power of two */
119 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
121 /* token symbol management */
122 typedef struct TokenSym
{
123 struct TokenSym
*hash_next
;
124 struct Sym
*sym_define
; /* direct pointer to define */
125 struct Sym
*sym_label
; /* direct pointer to label */
126 struct Sym
*sym_struct
; /* direct pointer to structure */
127 struct Sym
*sym_identifier
; /* direct pointer to identifier */
128 int tok
; /* token number */
133 typedef struct CString
{
134 int size
; /* size in bytes */
135 void *data
; /* either 'char *' or 'int *' */
137 void *data_allocated
; /* if non NULL, data has been malloced */
140 /* type definition */
141 typedef struct CType
{
147 typedef union CValue
{
153 unsigned int ul
; /* address (should be unsigned long on 64 bit cpu) */
155 unsigned long long ull
;
156 struct CString
*cstr
;
162 typedef struct SValue
{
163 CType type
; /* type */
164 unsigned short r
; /* register + flags */
165 unsigned short r2
; /* second register, used for 'long long'
166 type. If not used, set to VT_CONST */
167 CValue c
; /* constant, if VT_CONST */
168 struct Sym
*sym
; /* symbol, if (VT_SYM | VT_CONST) */
171 /* symbol management */
173 int v
; /* symbol token */
174 int r
; /* associated register */
175 int c
; /* associated number */
176 CType type
; /* associated type */
177 struct Sym
*next
; /* next related symbol */
178 struct Sym
*prev
; /* prev symbol in stack */
179 struct Sym
*prev_tok
; /* previous symbol for this token */
182 /* section definition */
183 /* XXX: use directly ELF structure for parameters ? */
184 /* special flag to indicate that the section should not be linked to
186 #define SHF_PRIVATE 0x80000000
188 typedef struct Section
{
189 unsigned long data_offset
; /* current data offset */
190 unsigned char *data
; /* section data */
191 unsigned long data_allocated
; /* used for realloc() handling */
192 int sh_name
; /* elf section name (only used during output) */
193 int sh_num
; /* elf section number */
194 int sh_type
; /* elf section type */
195 int sh_flags
; /* elf section flags */
196 int sh_info
; /* elf section info */
197 int sh_addralign
; /* elf section alignment */
198 int sh_entsize
; /* elf entry size */
199 unsigned long sh_size
; /* section size (only used during output) */
200 unsigned long sh_addr
; /* address at which the section is relocated */
201 unsigned long sh_offset
; /* address at which the section is relocated */
202 int nb_hashed_syms
; /* used to resize the hash table */
203 struct Section
*link
; /* link to another section */
204 struct Section
*reloc
; /* corresponding section for relocation, if any */
205 struct Section
*hash
; /* hash table for symbols */
206 struct Section
*next
;
207 char name
[1]; /* section name */
210 typedef struct DLLReference
{
215 /* GNUC attribute definition */
216 typedef struct AttributeDef
{
220 unsigned char func_call
; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
223 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
224 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
225 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
227 /* stored in 'Sym.c' field */
228 #define FUNC_NEW 1 /* ansi function prototype */
229 #define FUNC_OLD 2 /* old function prototype */
230 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
232 /* stored in 'Sym.r' field */
233 #define FUNC_CDECL 0 /* standard c call */
234 #define FUNC_STDCALL 1 /* pascal c call */
235 #define FUNC_FASTCALL1 2 /* first param in %eax */
236 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
237 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
239 /* field 'Sym.t' for macros */
240 #define MACRO_OBJ 0 /* object like macro */
241 #define MACRO_FUNC 1 /* function like macro */
243 /* field 'Sym.r' for C labels */
244 #define LABEL_DEFINED 0 /* label is defined */
245 #define LABEL_FORWARD 1 /* label is forward defined */
246 #define LABEL_DECLARED 2 /* label is declared but never used */
248 /* type_decl() types */
249 #define TYPE_ABSTRACT 1 /* type without variable */
250 #define TYPE_DIRECT 2 /* type with variable */
252 #define IO_BUF_SIZE 8192
254 typedef struct BufferedFile
{
258 int line_num
; /* current line number - here to simplify code */
259 int ifndef_macro
; /* #ifndef macro / #endif search */
260 int ifndef_macro_saved
; /* saved ifndef_macro */
261 int *ifdef_stack_ptr
; /* ifdef_stack value at the start of the file */
262 char inc_type
; /* type of include */
263 char inc_filename
[512]; /* filename specified by the user */
264 char filename
[1024]; /* current filename - here to simplify code */
265 unsigned char buffer
[IO_BUF_SIZE
+ 1]; /* extra size for CH_EOB char */
268 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
269 #define CH_EOF (-1) /* end of file */
271 /* parsing state (used to save parser state to reparse part of the
272 source several times) */
273 typedef struct ParseState
{
280 /* used to record tokens */
281 typedef struct TokenString
{
288 /* include file cache, used to find files faster and also to eliminate
289 inclusion if the include file is protected by #ifndef ... #endif */
290 typedef struct CachedInclude
{
292 int hash_next
; /* -1 if none */
293 char type
; /* '"' or '>' to give include type */
294 char filename
[1]; /* path specified in #include */
297 #define CACHED_INCLUDES_HASH_SIZE 512
300 static struct BufferedFile
*file
;
303 static CString tokcstr
; /* current parsed string, if any */
304 /* additional informations about token */
305 static int tok_flags
;
306 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
307 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
308 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
310 static int *macro_ptr
, *macro_ptr_allocated
;
311 static int *unget_saved_macro_ptr
;
312 static int unget_saved_buffer
[TOK_MAX_SIZE
+ 1];
313 static int unget_buffer_enabled
;
314 static int parse_flags
;
315 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
316 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
317 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
318 token. line feed is also
320 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
322 static Section
*text_section
, *data_section
, *bss_section
; /* predefined sections */
323 static Section
*cur_text_section
; /* current section where function code is
325 #ifdef CONFIG_TCC_ASM
326 static Section
*last_text_section
; /* to handle .previous asm directive */
328 /* bound check related sections */
329 static Section
*bounds_section
; /* contains global data bound description */
330 static Section
*lbounds_section
; /* contains local data bound description */
331 /* symbol sections */
332 static Section
*symtab_section
, *strtab_section
;
335 static Section
*stab_section
, *stabstr_section
;
337 /* loc : local variable index
338 ind : output code index
340 anon_sym: anonymous symbol index
342 static int rsym
, anon_sym
, ind
, loc
;
343 /* expression generation modifiers */
344 static int const_wanted
; /* true if constant wanted */
345 static int nocode_wanted
; /* true if no code generation wanted for an expression */
346 static int global_expr
; /* true if compound literals must be allocated
347 globally (used during initializers parsing */
348 static CType func_vt
; /* current function return type (used by return
351 static int last_line_num
, last_ind
, func_ind
; /* debug last line number and pc */
352 static int tok_ident
;
353 static TokenSym
**table_ident
;
354 static TokenSym
*hash_ident
[TOK_HASH_SIZE
];
355 static char token_buf
[STRING_MAX_SIZE
+ 1];
356 static char *funcname
;
357 static Sym
*global_stack
, *local_stack
;
358 static Sym
*define_stack
;
359 static Sym
*global_label_stack
, *local_label_stack
;
360 /* symbol allocator */
361 #define SYM_POOL_NB (8192 / sizeof(Sym))
362 static Sym
*sym_free_first
;
364 static SValue vstack
[VSTACK_SIZE
], *vtop
;
365 /* some predefined types */
366 static CType char_pointer_type
, func_old_type
, int_type
;
367 /* true if isid(c) || isnum(c) */
368 static unsigned char isidnum_table
[256];
370 /* compile with debug symbol (and use them if error during execution) */
371 static int do_debug
= 0;
373 /* compile with built-in memory and bounds checker */
374 static int do_bounds_check
= 0;
376 /* display benchmark infos */
378 static int do_bench
= 0;
380 static int total_lines
;
381 static int total_bytes
;
383 /* use GNU C extensions */
384 static int gnu_ext
= 1;
386 /* use Tiny C extensions */
387 static int tcc_ext
= 1;
389 /* max number of callers shown if error */
390 static int num_callers
= 6;
391 static const char **rt_bound_error_msg
;
393 /* XXX: get rid of this ASAP */
394 static struct TCCState
*tcc_state
;
396 /* give the path of the tcc libraries */
397 static const char *tcc_lib_path
= CONFIG_TCC_LIBDIR
"/tcc";
402 BufferedFile
**include_stack_ptr
;
403 int *ifdef_stack_ptr
;
405 /* include file handling */
406 char **include_paths
;
407 int nb_include_paths
;
408 char **sysinclude_paths
;
409 int nb_sysinclude_paths
;
410 CachedInclude
**cached_includes
;
411 int nb_cached_includes
;
413 char **library_paths
;
414 int nb_library_paths
;
416 /* array of all loaded dlls (including those referenced by loaded
418 DLLReference
**loaded_dlls
;
423 int nb_sections
; /* number of sections, including first dummy section */
428 unsigned long *got_offsets
;
430 /* give the correspondance from symtab indexes to dynsym indexes */
431 int *symtab_to_dynsym
;
433 /* temporary dynamic symbol sections (for dll loading) */
434 Section
*dynsymtab_section
;
435 /* exported dynamic symbol section */
438 int nostdinc
; /* if true, no standard headers are added */
439 int nostdlib
; /* if true, no standard libraries are added */
441 int nocommon
; /* if true, do not use common symbols for .bss data */
443 /* if true, static linking is performed */
446 /* if true, all symbols are exported */
449 /* if true, only link in referenced objects from archive */
452 /* address of text section */
453 unsigned long text_addr
;
456 /* output format, see TCC_OUTPUT_FORMAT_xxx */
459 /* C language options */
460 int char_is_unsigned
;
462 /* warning switches */
463 int warn_write_strings
;
464 int warn_unsupported
;
467 int warn_implicit_function_declaration
;
471 void (*error_func
)(void *opaque
, const char *msg
);
472 int error_set_jmp_enabled
;
473 jmp_buf error_jmp_buf
;
476 /* tiny assembler state */
479 /* see include_stack_ptr */
480 BufferedFile
*include_stack
[INCLUDE_STACK_SIZE
];
482 /* see ifdef_stack_ptr */
483 int ifdef_stack
[IFDEF_STACK_SIZE
];
485 /* see cached_includes */
486 int cached_includes_hash
[CACHED_INCLUDES_HASH_SIZE
];
489 /* The current value can be: */
490 #define VT_VALMASK 0x00ff
491 #define VT_CONST 0x00f0 /* constant in vc
492 (must be first non register value) */
493 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
494 #define VT_LOCAL 0x00f2 /* offset on stack */
495 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
496 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
497 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
498 #define VT_LVAL 0x0100 /* var is an lvalue */
499 #define VT_SYM 0x0200 /* a symbol value is added */
500 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
501 char/short stored in integer registers) */
502 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
503 dereferencing value */
504 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
505 bounding function call point is in vc */
506 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
507 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
508 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
509 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
512 #define VT_INT 0 /* integer type */
513 #define VT_BYTE 1 /* signed byte type */
514 #define VT_SHORT 2 /* short type */
515 #define VT_VOID 3 /* void type */
516 #define VT_PTR 4 /* pointer */
517 #define VT_ENUM 5 /* enum definition */
518 #define VT_FUNC 6 /* function type */
519 #define VT_STRUCT 7 /* struct/union definition */
520 #define VT_FLOAT 8 /* IEEE float */
521 #define VT_DOUBLE 9 /* IEEE double */
522 #define VT_LDOUBLE 10 /* IEEE long double */
523 #define VT_BOOL 11 /* ISOC99 boolean type */
524 #define VT_LLONG 12 /* 64 bit integer */
525 #define VT_LONG 13 /* long integer (NEVER USED as type, only
527 #define VT_BTYPE 0x000f /* mask for basic type */
528 #define VT_UNSIGNED 0x0010 /* unsigned type */
529 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
530 #define VT_BITFIELD 0x0040 /* bitfield modifier */
531 #define VT_CONSTANT 0x0800 /* const modifier */
532 #define VT_VOLATILE 0x1000 /* volatile modifier */
533 #define VT_SIGNED 0x2000 /* signed type */
536 #define VT_EXTERN 0x00000080 /* extern definition */
537 #define VT_STATIC 0x00000100 /* static variable */
538 #define VT_TYPEDEF 0x00000200 /* typedef definition */
539 #define VT_INLINE 0x00000400 /* inline definition */
541 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
543 /* type mask (except storage) */
544 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
545 #define VT_TYPE (~(VT_STORAGE))
549 /* warning: the following compare tokens depend on i386 asm code */
561 #define TOK_LAND 0xa0
565 #define TOK_MID 0xa3 /* inc/dec, to void constant */
567 #define TOK_UDIV 0xb0 /* unsigned division */
568 #define TOK_UMOD 0xb1 /* unsigned modulo */
569 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
570 #define TOK_CINT 0xb3 /* number in tokc */
571 #define TOK_CCHAR 0xb4 /* char constant in tokc */
572 #define TOK_STR 0xb5 /* pointer to string in tokc */
573 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
574 #define TOK_LCHAR 0xb7
575 #define TOK_LSTR 0xb8
576 #define TOK_CFLOAT 0xb9 /* float constant */
577 #define TOK_LINENUM 0xba /* line number info */
578 #define TOK_CDOUBLE 0xc0 /* double constant */
579 #define TOK_CLDOUBLE 0xc1 /* long double constant */
580 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
581 #define TOK_ADDC1 0xc3 /* add with carry generation */
582 #define TOK_ADDC2 0xc4 /* add with carry use */
583 #define TOK_SUBC1 0xc5 /* add with carry generation */
584 #define TOK_SUBC2 0xc6 /* add with carry use */
585 #define TOK_CUINT 0xc8 /* unsigned int constant */
586 #define TOK_CLLONG 0xc9 /* long long constant */
587 #define TOK_CULLONG 0xca /* unsigned long long constant */
588 #define TOK_ARROW 0xcb
589 #define TOK_DOTS 0xcc /* three dots */
590 #define TOK_SHR 0xcd /* unsigned shift right */
591 #define TOK_PPNUM 0xce /* preprocessor number */
593 #define TOK_SHL 0x01 /* shift left */
594 #define TOK_SAR 0x02 /* signed shift right */
596 /* assignement operators : normal operator or 0x80 */
597 #define TOK_A_MOD 0xa5
598 #define TOK_A_AND 0xa6
599 #define TOK_A_MUL 0xaa
600 #define TOK_A_ADD 0xab
601 #define TOK_A_SUB 0xad
602 #define TOK_A_DIV 0xaf
603 #define TOK_A_XOR 0xde
604 #define TOK_A_OR 0xfc
605 #define TOK_A_SHL 0x81
606 #define TOK_A_SAR 0x82
609 #define offsetof(type, field) ((size_t) &((type *)0)->field)
613 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
616 /* WARNING: the content of this string encodes token numbers */
617 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";
619 #define TOK_EOF (-1) /* end of file */
620 #define TOK_LINEFEED 10 /* line feed */
622 /* all identificators and strings have token above that */
623 #define TOK_IDENT 256
625 /* only used for i386 asm opcodes definitions */
626 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
629 DEF(TOK_ASM_ ## x ## b, #x "b") \
630 DEF(TOK_ASM_ ## x ## w, #x "w") \
631 DEF(TOK_ASM_ ## x ## l, #x "l") \
632 DEF(TOK_ASM_ ## x, #x)
635 DEF(TOK_ASM_ ## x ## w, #x "w") \
636 DEF(TOK_ASM_ ## x ## l, #x "l") \
637 DEF(TOK_ASM_ ## x, #x)
640 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
641 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
642 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
643 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
646 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
647 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
650 #define DEF_ASMTEST(x) \
682 #define TOK_ASM_int TOK_INT
685 TOK_LAST
= TOK_IDENT
- 1,
686 #define DEF(id, str) id,
691 static const char tcc_keywords
[] =
692 #define DEF(id, str) str "\0"
697 #define TOK_UIDENT TOK_DEFINE
700 #define snprintf _snprintf
701 #define vsnprintf _vsnprintf
704 #if defined(WIN32) || defined(TCC_UCLIBC) || defined(__FreeBSD__)
705 /* currently incorrect */
706 long double strtold(const char *nptr
, char **endptr
)
708 return (long double)strtod(nptr
, endptr
);
710 float strtof(const char *nptr
, char **endptr
)
712 return (float)strtod(nptr
, endptr
);
715 /* XXX: need to define this to use them in non ISOC99 context */
716 extern float strtof (const char *__nptr
, char **__endptr
);
717 extern long double strtold (const char *__nptr
, char **__endptr
);
720 static char *pstrcpy(char *buf
, int buf_size
, const char *s
);
721 static char *pstrcat(char *buf
, int buf_size
, const char *s
);
723 static void next(void);
724 static void next_nomacro(void);
725 static void parse_expr_type(CType
*type
);
726 static void expr_type(CType
*type
);
727 static void unary_type(CType
*type
);
728 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
729 int case_reg
, int is_expr
);
730 static int expr_const(void);
731 static void expr_eq(void);
732 static void gexpr(void);
733 static void gen_inline_functions(void);
734 static void decl(int l
);
735 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
736 int first
, int size_only
);
737 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
738 int has_init
, int v
, int scope
);
740 void gv2(int rc1
, int rc2
);
741 void move_reg(int r
, int s
);
742 void save_regs(int n
);
743 void save_reg(int r
);
748 int get_reg_ex(int rc
,int rc2
);
750 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
751 const int *macro_str
, int can_read_stream
);
753 void force_charshort_cast(int t
);
754 static void gen_cast(CType
*type
);
756 static Sym
*sym_find(int v
);
757 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
);
760 static int type_size(CType
*type
, int *a
);
761 static inline CType
*pointed_type(CType
*type
);
762 static int pointed_size(CType
*type
);
763 static int lvalue_type(int t
);
764 static int parse_btype(CType
*type
, AttributeDef
*ad
);
765 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
);
766 static int is_compatible_types(CType
*type1
, CType
*type2
);
768 int ieee_finite(double d
);
769 void error(const char *fmt
, ...);
773 void lexpand_nr(void);
774 static void vpush_global_sym(CType
*type
, int v
);
775 void vset(CType
*type
, int r
, int v
);
776 void type_to_str(char *buf
, int buf_size
,
777 CType
*type
, const char *varstr
);
778 char *get_tok_str(int v
, CValue
*cv
);
779 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
780 unsigned long offset
, unsigned long size
);
781 static Sym
*external_global_sym(int v
, CType
*type
, int r
);
783 /* section generation */
784 static void section_realloc(Section
*sec
, unsigned long new_size
);
785 static void *section_ptr_add(Section
*sec
, unsigned long size
);
786 static void put_extern_sym(Sym
*sym
, Section
*section
,
787 unsigned long value
, unsigned long size
);
788 static void greloc(Section
*s
, Sym
*sym
, unsigned long addr
, int type
);
789 static int put_elf_str(Section
*s
, const char *sym
);
790 static int put_elf_sym(Section
*s
,
791 unsigned long value
, unsigned long size
,
792 int info
, int other
, int shndx
, const char *name
);
793 static int add_elf_sym(Section
*s
, unsigned long value
, unsigned long size
,
794 int info
, int sh_num
, const char *name
);
795 static void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
796 int type
, int symbol
);
797 static void put_stabs(const char *str
, int type
, int other
, int desc
,
798 unsigned long value
);
799 static void put_stabs_r(const char *str
, int type
, int other
, int desc
,
800 unsigned long value
, Section
*sec
, int sym_index
);
801 static void put_stabn(int type
, int other
, int desc
, int value
);
802 static void put_stabd(int type
, int other
, int desc
);
803 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
);
805 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
806 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
807 static int tcc_add_file_internal(TCCState
*s
, const char *filename
, int flags
);
810 int tcc_output_coff(TCCState
*s1
, FILE *f
);
814 #ifdef CONFIG_TCC_ASM
816 typedef struct ExprValue
{
821 #define MAX_ASM_OPERANDS 30
823 typedef struct ASMOperand
{
824 int id
; /* GCC 3 optionnal identifier (0 if number only supported */
826 char asm_str
[16]; /* computed asm string for operand */
827 SValue
*vt
; /* C value of the expression */
828 int ref_index
; /* if >= 0, gives reference to a output constraint */
829 int input_index
; /* if >= 0, gives reference to an input constraint */
830 int priority
; /* priority, used to assign registers */
831 int reg
; /* if >= 0, register number used for this operand */
832 int is_llong
; /* true if double register value */
833 int is_memory
; /* true if memory operand */
834 int is_rw
; /* for '+' modifier */
837 static void asm_expr(TCCState
*s1
, ExprValue
*pe
);
838 static int asm_int_expr(TCCState
*s1
);
839 static int find_constraint(ASMOperand
*operands
, int nb_operands
,
840 const char *name
, const char **pp
);
842 static int tcc_assemble(TCCState
*s1
, int do_preprocess
);
846 static void asm_instr(void);
847 static void asm_global_instr(void);
849 /* true if float/double/long double type */
850 static inline int is_float(int t
)
854 return bt
== VT_LDOUBLE
|| bt
== VT_DOUBLE
|| bt
== VT_FLOAT
;
857 #ifdef TCC_TARGET_I386
858 #include "i386-gen.c"
861 #ifdef TCC_TARGET_ARM
865 #ifdef TCC_TARGET_C67
869 #ifdef CONFIG_TCC_STATIC
871 #define RTLD_LAZY 0x001
872 #define RTLD_NOW 0x002
873 #define RTLD_GLOBAL 0x100
874 #define RTLD_DEFAULT NULL
876 /* dummy function for profiling */
877 void *dlopen(const char *filename
, int flag
)
882 const char *dlerror(void)
887 typedef struct TCCSyms
{
892 #define TCCSYM(a) { #a, &a, },
894 /* add the symbol you want here if no dynamic linking is done */
895 static TCCSyms tcc_syms
[] = {
896 #if !defined(CONFIG_TCCBOOT)
905 void *dlsym(void *handle
, const char *symbol
)
909 while (p
->str
!= NULL
) {
910 if (!strcmp(p
->str
, symbol
))
919 /********************************************************/
921 /* we use our own 'finite' function to avoid potential problems with
922 non standard math libs */
923 /* XXX: endianness dependent */
924 int ieee_finite(double d
)
927 return ((unsigned)((p
[1] | 0x800fffff) + 1)) >> 31;
930 /* copy a string and truncate it. */
931 static char *pstrcpy(char *buf
, int buf_size
, const char *s
)
938 q_end
= buf
+ buf_size
- 1;
950 /* strcat and truncate. */
951 static char *pstrcat(char *buf
, int buf_size
, const char *s
)
956 pstrcpy(buf
+ len
, buf_size
- len
, s
);
960 static int strstart(const char *str
, const char *val
, const char **ptr
)
976 /* memory management */
982 static inline void tcc_free(void *ptr
)
985 mem_cur_size
-= malloc_usable_size(ptr
);
990 static void *tcc_malloc(unsigned long size
)
995 error("memory full");
997 mem_cur_size
+= malloc_usable_size(ptr
);
998 if (mem_cur_size
> mem_max_size
)
999 mem_max_size
= mem_cur_size
;
1004 static void *tcc_mallocz(unsigned long size
)
1007 ptr
= tcc_malloc(size
);
1008 memset(ptr
, 0, size
);
1012 static inline void *tcc_realloc(void *ptr
, unsigned long size
)
1016 mem_cur_size
-= malloc_usable_size(ptr
);
1018 ptr1
= realloc(ptr
, size
);
1020 /* NOTE: count not correct if alloc error, but not critical */
1021 mem_cur_size
+= malloc_usable_size(ptr1
);
1022 if (mem_cur_size
> mem_max_size
)
1023 mem_max_size
= mem_cur_size
;
1028 static char *tcc_strdup(const char *str
)
1031 ptr
= tcc_malloc(strlen(str
) + 1);
1036 #define free(p) use_tcc_free(p)
1037 #define malloc(s) use_tcc_malloc(s)
1038 #define realloc(p, s) use_tcc_realloc(p, s)
1040 static void dynarray_add(void ***ptab
, int *nb_ptr
, void *data
)
1047 /* every power of two we double array size */
1048 if ((nb
& (nb
- 1)) == 0) {
1053 pp
= tcc_realloc(pp
, nb_alloc
* sizeof(void *));
1055 error("memory full");
1062 /* symbol allocator */
1063 static Sym
*__sym_malloc(void)
1065 Sym
*sym_pool
, *sym
, *last_sym
;
1068 sym_pool
= tcc_malloc(SYM_POOL_NB
* sizeof(Sym
));
1070 last_sym
= sym_free_first
;
1072 for(i
= 0; i
< SYM_POOL_NB
; i
++) {
1073 sym
->next
= last_sym
;
1077 sym_free_first
= last_sym
;
1081 static inline Sym
*sym_malloc(void)
1084 sym
= sym_free_first
;
1086 sym
= __sym_malloc();
1087 sym_free_first
= sym
->next
;
1091 static inline void sym_free(Sym
*sym
)
1093 sym
->next
= sym_free_first
;
1094 sym_free_first
= sym
;
1097 Section
*new_section(TCCState
*s1
, const char *name
, int sh_type
, int sh_flags
)
1101 sec
= tcc_mallocz(sizeof(Section
) + strlen(name
));
1102 strcpy(sec
->name
, name
);
1103 sec
->sh_type
= sh_type
;
1104 sec
->sh_flags
= sh_flags
;
1111 sec
->sh_addralign
= 4;
1114 sec
->sh_addralign
= 1;
1117 sec
->sh_addralign
= 32; /* default conservative alignment */
1121 /* only add section if not private */
1122 if (!(sh_flags
& SHF_PRIVATE
)) {
1123 sec
->sh_num
= s1
->nb_sections
;
1124 dynarray_add((void ***)&s1
->sections
, &s1
->nb_sections
, sec
);
1129 static void free_section(Section
*s
)
1135 /* realloc section and set its content to zero */
1136 static void section_realloc(Section
*sec
, unsigned long new_size
)
1139 unsigned char *data
;
1141 size
= sec
->data_allocated
;
1144 while (size
< new_size
)
1146 data
= tcc_realloc(sec
->data
, size
);
1148 error("memory full");
1149 memset(data
+ sec
->data_allocated
, 0, size
- sec
->data_allocated
);
1151 sec
->data_allocated
= size
;
1154 /* reserve at least 'size' bytes in section 'sec' from
1155 sec->data_offset. */
1156 static void *section_ptr_add(Section
*sec
, unsigned long size
)
1158 unsigned long offset
, offset1
;
1160 offset
= sec
->data_offset
;
1161 offset1
= offset
+ size
;
1162 if (offset1
> sec
->data_allocated
)
1163 section_realloc(sec
, offset1
);
1164 sec
->data_offset
= offset1
;
1165 return sec
->data
+ offset
;
1168 /* return a reference to a section, and create it if it does not
1170 Section
*find_section(TCCState
*s1
, const char *name
)
1174 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1175 sec
= s1
->sections
[i
];
1176 if (!strcmp(name
, sec
->name
))
1179 /* sections are created as PROGBITS */
1180 return new_section(s1
, name
, SHT_PROGBITS
, SHF_ALLOC
);
1183 #define SECTION_ABS ((void *)1)
1185 /* update sym->c so that it points to an external symbol in section
1186 'section' with value 'value' */
1187 static void put_extern_sym(Sym
*sym
, Section
*section
,
1188 unsigned long value
, unsigned long size
)
1190 int sym_type
, sym_bind
, sh_num
, info
;
1194 if (section
== NULL
)
1196 else if (section
== SECTION_ABS
)
1199 sh_num
= section
->sh_num
;
1201 if ((sym
->type
.t
& VT_BTYPE
) == VT_FUNC
)
1202 sym_type
= STT_FUNC
;
1204 sym_type
= STT_OBJECT
;
1205 if (sym
->type
.t
& VT_STATIC
)
1206 sym_bind
= STB_LOCAL
;
1208 sym_bind
= STB_GLOBAL
;
1210 name
= get_tok_str(sym
->v
, NULL
);
1211 #ifdef CONFIG_TCC_BCHECK
1212 if (do_bounds_check
) {
1215 /* XXX: avoid doing that for statics ? */
1216 /* if bound checking is activated, we change some function
1217 names by adding the "__bound" prefix */
1220 /* XXX: we rely only on malloc hooks */
1232 strcpy(buf
, "__bound_");
1239 info
= ELF32_ST_INFO(sym_bind
, sym_type
);
1240 sym
->c
= add_elf_sym(symtab_section
, value
, size
, info
, sh_num
, name
);
1242 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
1243 esym
->st_value
= value
;
1244 esym
->st_size
= size
;
1245 esym
->st_shndx
= sh_num
;
1249 /* add a new relocation entry to symbol 'sym' in section 's' */
1250 static void greloc(Section
*s
, Sym
*sym
, unsigned long offset
, int type
)
1253 put_extern_sym(sym
, NULL
, 0, 0);
1254 /* now we can add ELF relocation info */
1255 put_elf_reloc(symtab_section
, s
, offset
, type
, sym
->c
);
1258 static inline int isid(int c
)
1260 return (c
>= 'a' && c
<= 'z') ||
1261 (c
>= 'A' && c
<= 'Z') ||
1265 static inline int isnum(int c
)
1267 return c
>= '0' && c
<= '9';
1270 static inline int isoct(int c
)
1272 return c
>= '0' && c
<= '7';
1275 static inline int toup(int c
)
1277 if (c
>= 'a' && c
<= 'z')
1278 return c
- 'a' + 'A';
1283 static void strcat_vprintf(char *buf
, int buf_size
, const char *fmt
, va_list ap
)
1287 vsnprintf(buf
+ len
, buf_size
- len
, fmt
, ap
);
1290 static void strcat_printf(char *buf
, int buf_size
, const char *fmt
, ...)
1294 strcat_vprintf(buf
, buf_size
, fmt
, ap
);
1298 void error1(TCCState
*s1
, int is_warning
, const char *fmt
, va_list ap
)
1305 for(f
= s1
->include_stack
; f
< s1
->include_stack_ptr
; f
++)
1306 strcat_printf(buf
, sizeof(buf
), "In file included from %s:%d:\n",
1307 (*f
)->filename
, (*f
)->line_num
);
1308 if (file
->line_num
> 0) {
1309 strcat_printf(buf
, sizeof(buf
),
1310 "%s:%d: ", file
->filename
, file
->line_num
);
1312 strcat_printf(buf
, sizeof(buf
),
1313 "%s: ", file
->filename
);
1316 strcat_printf(buf
, sizeof(buf
),
1320 strcat_printf(buf
, sizeof(buf
), "warning: ");
1321 strcat_vprintf(buf
, sizeof(buf
), fmt
, ap
);
1323 if (!s1
->error_func
) {
1324 /* default case: stderr */
1325 fprintf(stderr
, "%s\n", buf
);
1327 s1
->error_func(s1
->error_opaque
, buf
);
1329 if (!is_warning
|| s1
->warn_error
)
1334 void tcc_set_error_func(TCCState
*s
, void *error_opaque
,
1335 void (*error_func
)(void *opaque
, const char *msg
))
1337 s
->error_opaque
= error_opaque
;
1338 s
->error_func
= error_func
;
1342 /* error without aborting current compilation */
1343 void error_noabort(const char *fmt
, ...)
1345 TCCState
*s1
= tcc_state
;
1349 error1(s1
, 0, fmt
, ap
);
1353 void error(const char *fmt
, ...)
1355 TCCState
*s1
= tcc_state
;
1359 error1(s1
, 0, fmt
, ap
);
1361 /* better than nothing: in some cases, we accept to handle errors */
1362 if (s1
->error_set_jmp_enabled
) {
1363 longjmp(s1
->error_jmp_buf
, 1);
1365 /* XXX: eliminate this someday */
1370 void expect(const char *msg
)
1372 error("%s expected", msg
);
1375 void warning(const char *fmt
, ...)
1377 TCCState
*s1
= tcc_state
;
1384 error1(s1
, 1, fmt
, ap
);
1391 error("'%c' expected", c
);
1395 static void test_lvalue(void)
1397 if (!(vtop
->r
& VT_LVAL
))
1401 /* allocate a new token */
1402 static TokenSym
*tok_alloc_new(TokenSym
**pts
, const char *str
, int len
)
1404 TokenSym
*ts
, **ptable
;
1407 if (tok_ident
>= SYM_FIRST_ANOM
)
1408 error("memory full");
1410 /* expand token table if needed */
1411 i
= tok_ident
- TOK_IDENT
;
1412 if ((i
% TOK_ALLOC_INCR
) == 0) {
1413 ptable
= tcc_realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
1415 error("memory full");
1416 table_ident
= ptable
;
1419 ts
= tcc_malloc(sizeof(TokenSym
) + len
);
1420 table_ident
[i
] = ts
;
1421 ts
->tok
= tok_ident
++;
1422 ts
->sym_define
= NULL
;
1423 ts
->sym_label
= NULL
;
1424 ts
->sym_struct
= NULL
;
1425 ts
->sym_identifier
= NULL
;
1427 ts
->hash_next
= NULL
;
1428 memcpy(ts
->str
, str
, len
);
1429 ts
->str
[len
] = '\0';
1434 #define TOK_HASH_INIT 1
1435 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1437 /* find a token and add it if not found */
1438 static TokenSym
*tok_alloc(const char *str
, int len
)
1440 TokenSym
*ts
, **pts
;
1446 h
= TOK_HASH_FUNC(h
, ((unsigned char *)str
)[i
]);
1447 h
&= (TOK_HASH_SIZE
- 1);
1449 pts
= &hash_ident
[h
];
1454 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
1456 pts
= &(ts
->hash_next
);
1458 return tok_alloc_new(pts
, str
, len
);
1461 /* CString handling */
1463 static void cstr_realloc(CString
*cstr
, int new_size
)
1468 size
= cstr
->size_allocated
;
1470 size
= 8; /* no need to allocate a too small first string */
1471 while (size
< new_size
)
1473 data
= tcc_realloc(cstr
->data_allocated
, size
);
1475 error("memory full");
1476 cstr
->data_allocated
= data
;
1477 cstr
->size_allocated
= size
;
1482 static inline void cstr_ccat(CString
*cstr
, int ch
)
1485 size
= cstr
->size
+ 1;
1486 if (size
> cstr
->size_allocated
)
1487 cstr_realloc(cstr
, size
);
1488 ((unsigned char *)cstr
->data
)[size
- 1] = ch
;
1492 static void cstr_cat(CString
*cstr
, const char *str
)
1504 /* add a wide char */
1505 static void cstr_wccat(CString
*cstr
, int ch
)
1508 size
= cstr
->size
+ sizeof(int);
1509 if (size
> cstr
->size_allocated
)
1510 cstr_realloc(cstr
, size
);
1511 *(int *)(((unsigned char *)cstr
->data
) + size
- sizeof(int)) = ch
;
1515 static void cstr_new(CString
*cstr
)
1517 memset(cstr
, 0, sizeof(CString
));
1520 /* free string and reset it to NULL */
1521 static void cstr_free(CString
*cstr
)
1523 tcc_free(cstr
->data_allocated
);
1527 #define cstr_reset(cstr) cstr_free(cstr)
1529 /* XXX: unicode ? */
1530 static void add_char(CString
*cstr
, int c
)
1532 if (c
== '\'' || c
== '\"' || c
== '\\') {
1533 /* XXX: could be more precise if char or string */
1534 cstr_ccat(cstr
, '\\');
1536 if (c
>= 32 && c
<= 126) {
1539 cstr_ccat(cstr
, '\\');
1541 cstr_ccat(cstr
, 'n');
1543 cstr_ccat(cstr
, '0' + ((c
>> 6) & 7));
1544 cstr_ccat(cstr
, '0' + ((c
>> 3) & 7));
1545 cstr_ccat(cstr
, '0' + (c
& 7));
1550 /* XXX: buffer overflow */
1551 /* XXX: float tokens */
1552 char *get_tok_str(int v
, CValue
*cv
)
1554 static char buf
[STRING_MAX_SIZE
+ 1];
1555 static CString cstr_buf
;
1561 /* NOTE: to go faster, we give a fixed buffer for small strings */
1562 cstr_reset(&cstr_buf
);
1563 cstr_buf
.data
= buf
;
1564 cstr_buf
.size_allocated
= sizeof(buf
);
1570 /* XXX: not quite exact, but only useful for testing */
1571 sprintf(p
, "%u", cv
->ui
);
1575 /* XXX: not quite exact, but only useful for testing */
1576 sprintf(p
, "%Lu", cv
->ull
);
1580 cstr_ccat(&cstr_buf
, '\'');
1581 add_char(&cstr_buf
, cv
->i
);
1582 cstr_ccat(&cstr_buf
, '\'');
1583 cstr_ccat(&cstr_buf
, '\0');
1587 len
= cstr
->size
- 1;
1589 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1590 cstr_ccat(&cstr_buf
, '\0');
1595 cstr_ccat(&cstr_buf
, '\"');
1597 len
= cstr
->size
- 1;
1599 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1601 len
= (cstr
->size
/ sizeof(int)) - 1;
1603 add_char(&cstr_buf
, ((int *)cstr
->data
)[i
]);
1605 cstr_ccat(&cstr_buf
, '\"');
1606 cstr_ccat(&cstr_buf
, '\0');
1615 return strcpy(p
, "<<=");
1617 return strcpy(p
, ">>=");
1619 if (v
< TOK_IDENT
) {
1620 /* search in two bytes table */
1634 } else if (v
< tok_ident
) {
1635 return table_ident
[v
- TOK_IDENT
]->str
;
1636 } else if (v
>= SYM_FIRST_ANOM
) {
1637 /* special name for anonymous symbol */
1638 sprintf(p
, "L.%u", v
- SYM_FIRST_ANOM
);
1640 /* should never happen */
1645 return cstr_buf
.data
;
1648 /* push, without hashing */
1649 static Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
1663 /* find a symbol and return its associated structure. 's' is the top
1664 of the symbol stack */
1665 static Sym
*sym_find2(Sym
*s
, int v
)
1675 /* structure lookup */
1676 static inline Sym
*struct_find(int v
)
1679 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1681 return table_ident
[v
]->sym_struct
;
1684 /* find an identifier */
1685 static inline Sym
*sym_find(int v
)
1688 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1690 return table_ident
[v
]->sym_identifier
;
1693 /* push a given symbol on the symbol stack */
1694 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
)
1703 s
= sym_push2(ps
, v
, type
->t
, c
);
1704 s
->type
.ref
= type
->ref
;
1706 /* don't record fields or anonymous symbols */
1708 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1709 /* record symbol in token array */
1710 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1712 ps
= &ts
->sym_struct
;
1714 ps
= &ts
->sym_identifier
;
1721 /* push a global identifier */
1722 static Sym
*global_identifier_push(int v
, int t
, int c
)
1725 s
= sym_push2(&global_stack
, v
, t
, c
);
1726 /* don't record anonymous symbol */
1727 if (v
< SYM_FIRST_ANOM
) {
1728 ps
= &table_ident
[v
- TOK_IDENT
]->sym_identifier
;
1729 /* modify the top most local identifier, so that
1730 sym_identifier will point to 's' when popped */
1732 ps
= &(*ps
)->prev_tok
;
1739 /* pop symbols until top reaches 'b' */
1740 static void sym_pop(Sym
**ptop
, Sym
*b
)
1750 /* remove symbol in token array */
1752 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1753 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1755 ps
= &ts
->sym_struct
;
1757 ps
= &ts
->sym_identifier
;
1768 BufferedFile
*tcc_open(TCCState
*s1
, const char *filename
)
1773 fd
= open(filename
, O_RDONLY
| O_BINARY
);
1776 bf
= tcc_malloc(sizeof(BufferedFile
));
1782 bf
->buf_ptr
= bf
->buffer
;
1783 bf
->buf_end
= bf
->buffer
;
1784 bf
->buffer
[0] = CH_EOB
; /* put eob symbol */
1785 pstrcpy(bf
->filename
, sizeof(bf
->filename
), filename
);
1787 bf
->ifndef_macro
= 0;
1788 bf
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
1789 // printf("opening '%s'\n", filename);
1793 void tcc_close(BufferedFile
*bf
)
1795 total_lines
+= bf
->line_num
;
1800 /* fill input buffer and peek next char */
1801 static int tcc_peekc_slow(BufferedFile
*bf
)
1804 /* only tries to read if really end of buffer */
1805 if (bf
->buf_ptr
>= bf
->buf_end
) {
1807 #if defined(PARSE_DEBUG)
1812 len
= read(bf
->fd
, bf
->buffer
, len
);
1819 bf
->buf_ptr
= bf
->buffer
;
1820 bf
->buf_end
= bf
->buffer
+ len
;
1821 *bf
->buf_end
= CH_EOB
;
1823 if (bf
->buf_ptr
< bf
->buf_end
) {
1824 return bf
->buf_ptr
[0];
1826 bf
->buf_ptr
= bf
->buf_end
;
1831 /* return the current character, handling end of block if necessary
1833 static int handle_eob(void)
1835 return tcc_peekc_slow(file
);
1838 /* read next char from current input file and handle end of input buffer */
1839 static inline void inp(void)
1841 ch
= *(++(file
->buf_ptr
));
1842 /* end of buffer/file handling */
1847 /* handle '\[\r]\n' */
1848 static void handle_stray(void)
1850 while (ch
== '\\') {
1855 } else if (ch
== '\r') {
1863 error("stray '\\' in program");
1868 /* skip the stray and handle the \\n case. Output an error if
1869 incorrect char after the stray */
1870 static int handle_stray1(uint8_t *p
)
1874 if (p
>= file
->buf_end
) {
1891 /* handle just the EOB case, but not stray */
1892 #define PEEKC_EOB(c, p)\
1903 /* handle the complicated stray case */
1904 #define PEEKC(c, p)\
1909 c = handle_stray1(p);\
1914 /* input with '\[\r]\n' handling. Note that this function cannot
1915 handle other characters after '\', so you cannot call it inside
1916 strings or comments */
1917 static void minp(void)
1925 /* single line C++ comments */
1926 static uint8_t *parse_line_comment(uint8_t *p
)
1934 if (c
== '\n' || c
== CH_EOF
) {
1936 } else if (c
== '\\') {
1945 } else if (c
== '\r') {
1963 static uint8_t *parse_comment(uint8_t *p
)
1969 /* fast skip loop */
1972 if (c
== '\n' || c
== '*' || c
== '\\')
1976 if (c
== '\n' || c
== '*' || c
== '\\')
1980 /* now we can handle all the cases */
1984 } else if (c
== '*') {
1990 } else if (c
== '/') {
1991 goto end_of_comment
;
1992 } else if (c
== '\\') {
1997 /* skip '\[\r]\n', otherwise just skip the stray */
2003 } else if (c
== '\r') {
2020 /* stray, eob or eof */
2025 error("unexpected end of file in comment");
2026 } else if (c
== '\\') {
2038 /* space exlcuding newline */
2039 static inline int is_space(int ch
)
2041 return ch
== ' ' || ch
== '\t' || ch
== '\v' || ch
== '\f' || ch
== '\r';
2044 static inline void skip_spaces(void)
2046 while (is_space(ch
))
2050 /* parse a string without interpreting escapes */
2051 static uint8_t *parse_pp_string(uint8_t *p
,
2052 int sep
, CString
*str
)
2060 } else if (c
== '\\') {
2065 unterminated_string
:
2066 /* XXX: indicate line number of start of string */
2067 error("missing terminating %c character", sep
);
2068 } else if (c
== '\\') {
2069 /* escape : just skip \[\r]\n */
2074 } else if (c
== '\r') {
2077 expect("'\n' after '\r'");
2080 } else if (c
== CH_EOF
) {
2081 goto unterminated_string
;
2084 cstr_ccat(str
, '\\');
2090 } else if (c
== '\n') {
2093 } else if (c
== '\r') {
2097 cstr_ccat(str
, '\r');
2113 /* skip block of text until #else, #elif or #endif. skip also pairs of
2115 void preprocess_skip(void)
2117 int a
, start_of_line
, c
;
2144 } else if (c
== '\\') {
2145 /* XXX: incorrect: should not give an error */
2146 ch
= file
->buf_ptr
[0];
2154 p
= parse_pp_string(p
, c
, NULL
);
2163 p
= parse_comment(p
);
2164 } else if (ch
== '/') {
2165 p
= parse_line_comment(p
);
2171 if (start_of_line
) {
2176 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
2178 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
2180 else if (tok
== TOK_ENDIF
)
2194 /* ParseState handling */
2196 /* XXX: currently, no include file info is stored. Thus, we cannot display
2197 accurate messages if the function or data definition spans multiple
2200 /* save current parse state in 's' */
2201 void save_parse_state(ParseState
*s
)
2203 s
->line_num
= file
->line_num
;
2204 s
->macro_ptr
= macro_ptr
;
2209 /* restore parse state from 's' */
2210 void restore_parse_state(ParseState
*s
)
2212 file
->line_num
= s
->line_num
;
2213 macro_ptr
= s
->macro_ptr
;
2218 /* return the number of additional 'ints' necessary to store the
2220 static inline int tok_ext_size(int t
)
2234 error("unsupported token");
2241 return LDOUBLE_SIZE
/ 4;
2247 /* token string handling */
2249 static inline void tok_str_new(TokenString
*s
)
2253 s
->allocated_len
= 0;
2254 s
->last_line_num
= -1;
2257 static void tok_str_free(int *str
)
2262 static int *tok_str_realloc(TokenString
*s
)
2266 if (s
->allocated_len
== 0) {
2269 len
= s
->allocated_len
* 2;
2271 str
= tcc_realloc(s
->str
, len
* sizeof(int));
2273 error("memory full");
2274 s
->allocated_len
= len
;
2279 static void tok_str_add(TokenString
*s
, int t
)
2285 if (len
>= s
->allocated_len
)
2286 str
= tok_str_realloc(s
);
2291 static void tok_str_add2(TokenString
*s
, int t
, CValue
*cv
)
2298 /* allocate space for worst case */
2299 if (len
+ TOK_MAX_SIZE
> s
->allocated_len
)
2300 str
= tok_str_realloc(s
);
2309 str
[len
++] = cv
->tab
[0];
2318 nb_words
= (sizeof(CString
) + cv
->cstr
->size
+ 3) >> 2;
2319 while ((len
+ nb_words
) > s
->allocated_len
)
2320 str
= tok_str_realloc(s
);
2321 cstr
= (CString
*)(str
+ len
);
2323 cstr
->size
= cv
->cstr
->size
;
2324 cstr
->data_allocated
= NULL
;
2325 cstr
->size_allocated
= cstr
->size
;
2326 memcpy((char *)cstr
+ sizeof(CString
),
2327 cv
->cstr
->data
, cstr
->size
);
2334 #if LDOUBLE_SIZE == 8
2337 str
[len
++] = cv
->tab
[0];
2338 str
[len
++] = cv
->tab
[1];
2340 #if LDOUBLE_SIZE == 12
2342 str
[len
++] = cv
->tab
[0];
2343 str
[len
++] = cv
->tab
[1];
2344 str
[len
++] = cv
->tab
[2];
2345 #elif LDOUBLE_SIZE != 8
2346 #error add long double size support
2355 /* add the current parse token in token string 's' */
2356 static void tok_str_add_tok(TokenString
*s
)
2360 /* save line number info */
2361 if (file
->line_num
!= s
->last_line_num
) {
2362 s
->last_line_num
= file
->line_num
;
2363 cval
.i
= s
->last_line_num
;
2364 tok_str_add2(s
, TOK_LINENUM
, &cval
);
2366 tok_str_add2(s
, tok
, &tokc
);
2369 #if LDOUBLE_SIZE == 12
2370 #define LDOUBLE_GET(p, cv) \
2374 #elif LDOUBLE_SIZE == 8
2375 #define LDOUBLE_GET(p, cv) \
2379 #error add long double size support
2383 /* get a token from an integer array and increment pointer
2384 accordingly. we code it as a macro to avoid pointer aliasing. */
2385 #define TOK_GET(t, p, cv) \
2400 cv.cstr = (CString *)p; \
2401 cv.cstr->data = (char *)p + sizeof(CString);\
2402 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2411 case TOK_CLDOUBLE: \
2412 LDOUBLE_GET(p, cv); \
2413 p += LDOUBLE_SIZE / 4; \
2420 /* defines handling */
2421 static inline void define_push(int v
, int macro_type
, int *str
, Sym
*first_arg
)
2425 s
= sym_push2(&define_stack
, v
, macro_type
, (int)str
);
2426 s
->next
= first_arg
;
2427 table_ident
[v
- TOK_IDENT
]->sym_define
= s
;
2430 /* undefined a define symbol. Its name is just set to zero */
2431 static void define_undef(Sym
*s
)
2435 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2436 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2440 static inline Sym
*define_find(int v
)
2443 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2445 return table_ident
[v
]->sym_define
;
2448 /* free define stack until top reaches 'b' */
2449 static void free_defines(Sym
*b
)
2457 /* do not free args or predefined defines */
2459 tok_str_free((int *)top
->c
);
2461 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2462 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2470 static Sym
*label_find(int v
)
2473 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2475 return table_ident
[v
]->sym_label
;
2478 static Sym
*label_push(Sym
**ptop
, int v
, int flags
)
2481 s
= sym_push2(ptop
, v
, 0, 0);
2483 ps
= &table_ident
[v
- TOK_IDENT
]->sym_label
;
2484 if (ptop
== &global_label_stack
) {
2485 /* modify the top most local identifier, so that
2486 sym_identifier will point to 's' when popped */
2488 ps
= &(*ps
)->prev_tok
;
2495 /* pop labels until element last is reached. Look if any labels are
2496 undefined. Define symbols if '&&label' was used. */
2497 static void label_pop(Sym
**ptop
, Sym
*slast
)
2500 for(s
= *ptop
; s
!= slast
; s
= s1
) {
2502 if (s
->r
== LABEL_DECLARED
) {
2503 warning("label '%s' declared but not used", get_tok_str(s
->v
, NULL
));
2504 } else if (s
->r
== LABEL_FORWARD
) {
2505 error("label '%s' used but not defined",
2506 get_tok_str(s
->v
, NULL
));
2509 /* define corresponding symbol. A size of
2511 put_extern_sym(s
, cur_text_section
, (long)s
->next
, 1);
2515 table_ident
[s
->v
- TOK_IDENT
]->sym_label
= s
->prev_tok
;
2521 /* eval an expression for #if/#elif */
2522 static int expr_preprocess(void)
2528 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2529 next(); /* do macro subst */
2530 if (tok
== TOK_DEFINED
) {
2535 c
= define_find(tok
) != 0;
2540 } else if (tok
>= TOK_IDENT
) {
2541 /* if undefined macro */
2545 tok_str_add_tok(&str
);
2547 tok_str_add(&str
, -1); /* simulate end of file */
2548 tok_str_add(&str
, 0);
2549 /* now evaluate C constant expression */
2550 macro_ptr
= str
.str
;
2554 tok_str_free(str
.str
);
2558 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2559 static void tok_print(int *str
)
2565 TOK_GET(t
, str
, cval
);
2568 printf(" %s", get_tok_str(t
, &cval
));
2574 /* parse after #define */
2575 static void parse_define(void)
2577 Sym
*s
, *first
, **ps
;
2578 int v
, t
, varg
, is_vaargs
, c
;
2583 error("invalid macro name '%s'", get_tok_str(tok
, &tokc
));
2584 /* XXX: should check if same macro (ANSI) */
2587 /* '(' must be just after macro definition for MACRO_FUNC */
2588 c
= file
->buf_ptr
[0];
2590 c
= handle_stray1(file
->buf_ptr
);
2595 while (tok
!= ')') {
2599 if (varg
== TOK_DOTS
) {
2600 varg
= TOK___VA_ARGS__
;
2602 } else if (tok
== TOK_DOTS
&& gnu_ext
) {
2606 if (varg
< TOK_IDENT
)
2607 error("badly punctuated parameter list");
2608 s
= sym_push2(&define_stack
, varg
| SYM_FIELD
, is_vaargs
, 0);
2619 /* EOF testing necessary for '-D' handling */
2620 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2621 tok_str_add2(&str
, tok
, &tokc
);
2624 tok_str_add(&str
, 0);
2626 printf("define %s %d: ", get_tok_str(v
, NULL
), t
);
2629 define_push(v
, t
, str
.str
, first
);
2632 static inline int hash_cached_include(int type
, const char *filename
)
2634 const unsigned char *s
;
2638 h
= TOK_HASH_FUNC(h
, type
);
2641 h
= TOK_HASH_FUNC(h
, *s
);
2644 h
&= (CACHED_INCLUDES_HASH_SIZE
- 1);
2648 /* XXX: use a token or a hash table to accelerate matching ? */
2649 static CachedInclude
*search_cached_include(TCCState
*s1
,
2650 int type
, const char *filename
)
2654 h
= hash_cached_include(type
, filename
);
2655 i
= s1
->cached_includes_hash
[h
];
2659 e
= s1
->cached_includes
[i
- 1];
2660 if (e
->type
== type
&& !strcmp(e
->filename
, filename
))
2667 static inline void add_cached_include(TCCState
*s1
, int type
,
2668 const char *filename
, int ifndef_macro
)
2673 if (search_cached_include(s1
, type
, filename
))
2676 printf("adding cached '%s' %s\n", filename
, get_tok_str(ifndef_macro
, NULL
));
2678 e
= tcc_malloc(sizeof(CachedInclude
) + strlen(filename
));
2682 strcpy(e
->filename
, filename
);
2683 e
->ifndef_macro
= ifndef_macro
;
2684 dynarray_add((void ***)&s1
->cached_includes
, &s1
->nb_cached_includes
, e
);
2685 /* add in hash table */
2686 h
= hash_cached_include(type
, filename
);
2687 e
->hash_next
= s1
->cached_includes_hash
[h
];
2688 s1
->cached_includes_hash
[h
] = s1
->nb_cached_includes
;
2691 /* is_bof is true if first non space token at beginning of file */
2692 static void preprocess(int is_bof
)
2694 TCCState
*s1
= tcc_state
;
2695 int size
, i
, c
, n
, saved_parse_flags
;
2696 char buf
[1024], *q
, *p
;
2702 saved_parse_flags
= parse_flags
;
2703 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
|
2704 PARSE_FLAG_LINEFEED
;
2714 s
= define_find(tok
);
2715 /* undefine symbol by putting an invalid name */
2720 ch
= file
->buf_ptr
[0];
2721 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2726 } else if (ch
== '\"') {
2729 /* XXX: better stray handling */
2732 while (ch
!= c
&& ch
!= '\n' && ch
!= CH_EOF
) {
2733 if ((q
- buf
) < sizeof(buf
) - 1)
2740 /* eat all spaces and comments after include */
2741 /* XXX: slightly incorrect */
2742 while (ch1
!= '\n' && ch1
!= CH_EOF
)
2746 /* computed #include : either we have only strings or
2747 we have anything enclosed in '<>' */
2750 if (tok
== TOK_STR
) {
2751 while (tok
!= TOK_LINEFEED
) {
2752 if (tok
!= TOK_STR
) {
2754 error("'#include' expects \"FILENAME\" or <FILENAME>");
2756 pstrcat(buf
, sizeof(buf
), (char *)tokc
.cstr
->data
);
2762 while (tok
!= TOK_LINEFEED
) {
2763 pstrcat(buf
, sizeof(buf
), get_tok_str(tok
, &tokc
));
2767 /* check syntax and remove '<>' */
2768 if (len
< 2 || buf
[0] != '<' || buf
[len
- 1] != '>')
2769 goto include_syntax
;
2770 memmove(buf
, buf
+ 1, len
- 2);
2771 buf
[len
- 2] = '\0';
2776 e
= search_cached_include(s1
, c
, buf
);
2777 if (e
&& define_find(e
->ifndef_macro
)) {
2778 /* no need to parse the include because the 'ifndef macro'
2781 printf("%s: skipping %s\n", file
->filename
, buf
);
2785 /* first search in current dir if "header.h" */
2787 p
= strrchr(file
->filename
, '/');
2789 size
= p
+ 1 - file
->filename
;
2790 if (size
> sizeof(buf1
) - 1)
2791 size
= sizeof(buf1
) - 1;
2792 memcpy(buf1
, file
->filename
, size
);
2794 pstrcat(buf1
, sizeof(buf1
), buf
);
2795 f
= tcc_open(s1
, buf1
);
2799 if (s1
->include_stack_ptr
>= s1
->include_stack
+ INCLUDE_STACK_SIZE
)
2800 error("#include recursion too deep");
2801 /* now search in all the include paths */
2802 n
= s1
->nb_include_paths
+ s1
->nb_sysinclude_paths
;
2803 for(i
= 0; i
< n
; i
++) {
2805 if (i
< s1
->nb_include_paths
)
2806 path
= s1
->include_paths
[i
];
2808 path
= s1
->sysinclude_paths
[i
- s1
->nb_include_paths
];
2809 pstrcpy(buf1
, sizeof(buf1
), path
);
2810 pstrcat(buf1
, sizeof(buf1
), "/");
2811 pstrcat(buf1
, sizeof(buf1
), buf
);
2812 f
= tcc_open(s1
, buf1
);
2816 error("include file '%s' not found", buf
);
2820 printf("%s: including %s\n", file
->filename
, buf1
);
2823 pstrcpy(f
->inc_filename
, sizeof(f
->inc_filename
), buf
);
2824 /* push current file in stack */
2825 /* XXX: fix current line init */
2826 *s1
->include_stack_ptr
++ = file
;
2828 /* add include file debug info */
2830 put_stabs(file
->filename
, N_BINCL
, 0, 0, 0);
2832 tok_flags
|= TOK_FLAG_BOF
| TOK_FLAG_BOL
;
2833 ch
= file
->buf_ptr
[0];
2841 c
= expr_preprocess();
2847 if (tok
< TOK_IDENT
)
2848 error("invalid argument for '#if%sdef'", c
? "n" : "");
2852 printf("#ifndef %s\n", get_tok_str(tok
, NULL
));
2854 file
->ifndef_macro
= tok
;
2857 c
= (define_find(tok
) != 0) ^ c
;
2859 if (s1
->ifdef_stack_ptr
>= s1
->ifdef_stack
+ IFDEF_STACK_SIZE
)
2860 error("memory full");
2861 *s1
->ifdef_stack_ptr
++ = c
;
2864 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
2865 error("#else without matching #if");
2866 if (s1
->ifdef_stack_ptr
[-1] & 2)
2867 error("#else after #else");
2868 c
= (s1
->ifdef_stack_ptr
[-1] ^= 3);
2871 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
2872 error("#elif without matching #if");
2873 c
= s1
->ifdef_stack_ptr
[-1];
2875 error("#elif after #else");
2876 /* last #if/#elif expression was true: we skip */
2879 c
= expr_preprocess();
2880 s1
->ifdef_stack_ptr
[-1] = c
;
2890 if (s1
->ifdef_stack_ptr
<= file
->ifdef_stack_ptr
)
2891 error("#endif without matching #if");
2892 s1
->ifdef_stack_ptr
--;
2893 /* '#ifndef macro' was at the start of file. Now we check if
2894 an '#endif' is exactly at the end of file */
2895 if (file
->ifndef_macro
&&
2896 s1
->ifdef_stack_ptr
== file
->ifdef_stack_ptr
) {
2897 file
->ifndef_macro_saved
= file
->ifndef_macro
;
2898 /* need to set to zero to avoid false matches if another
2899 #ifndef at middle of file */
2900 file
->ifndef_macro
= 0;
2901 while (tok
!= TOK_LINEFEED
)
2903 tok_flags
|= TOK_FLAG_ENDIF
;
2909 if (tok
!= TOK_CINT
)
2911 file
->line_num
= tokc
.i
- 1; /* the line number will be incremented after */
2913 if (tok
!= TOK_LINEFEED
) {
2916 pstrcpy(file
->filename
, sizeof(file
->filename
),
2917 (char *)tokc
.cstr
->data
);
2923 ch
= file
->buf_ptr
[0];
2926 while (ch
!= '\n' && ch
!= CH_EOF
) {
2927 if ((q
- buf
) < sizeof(buf
) - 1)
2933 error("#error %s", buf
);
2935 warning("#warning %s", buf
);
2941 if (tok
== TOK_LINEFEED
|| tok
== '!' || tok
== TOK_CINT
) {
2942 /* '!' is ignored to allow C scripts. numbers are ignored
2943 to emulate cpp behaviour */
2945 if (!(saved_parse_flags
& PARSE_FLAG_ASM_COMMENTS
))
2946 error("invalid preprocessing directive #%s", get_tok_str(tok
, &tokc
));
2950 /* ignore other preprocess commands or #! for C scripts */
2951 while (tok
!= TOK_LINEFEED
)
2954 parse_flags
= saved_parse_flags
;
2957 /* evaluate escape codes in a string. */
2958 static void parse_escape_string(CString
*outstr
, const uint8_t *buf
, int is_long
)
2973 case '0': case '1': case '2': case '3':
2974 case '4': case '5': case '6': case '7':
2975 /* at most three octal digits */
2980 n
= n
* 8 + c
- '0';
2984 n
= n
* 8 + c
- '0';
2989 goto add_char_nonext
;
2995 if (c
>= 'a' && c
<= 'f')
2997 else if (c
>= 'A' && c
<= 'F')
3007 goto add_char_nonext
;
3031 goto invalid_escape
;
3041 if (c
>= '!' && c
<= '~')
3042 warning("unknown escape sequence: \'\\%c\'", c
);
3044 warning("unknown escape sequence: \'\\x%x\'", c
);
3051 cstr_ccat(outstr
, c
);
3053 cstr_wccat(outstr
, c
);
3055 /* add a trailing '\0' */
3057 cstr_ccat(outstr
, '\0');
3059 cstr_wccat(outstr
, '\0');
3062 /* we use 64 bit numbers */
3065 /* bn = (bn << shift) | or_val */
3066 void bn_lshift(unsigned int *bn
, int shift
, int or_val
)
3070 for(i
=0;i
<BN_SIZE
;i
++) {
3072 bn
[i
] = (v
<< shift
) | or_val
;
3073 or_val
= v
>> (32 - shift
);
3077 void bn_zero(unsigned int *bn
)
3080 for(i
=0;i
<BN_SIZE
;i
++) {
3085 /* parse number in null terminated string 'p' and return it in the
3087 void parse_number(const char *p
)
3089 int b
, t
, shift
, frac_bits
, s
, exp_val
, ch
;
3091 unsigned int bn
[BN_SIZE
];
3102 goto float_frac_parse
;
3103 } else if (t
== '0') {
3104 if (ch
== 'x' || ch
== 'X') {
3108 } else if (tcc_ext
&& (ch
== 'b' || ch
== 'B')) {
3114 /* parse all digits. cannot check octal numbers at this stage
3115 because of floating point constants */
3117 if (ch
>= 'a' && ch
<= 'f')
3119 else if (ch
>= 'A' && ch
<= 'F')
3127 if (q
>= token_buf
+ STRING_MAX_SIZE
) {
3129 error("number too long");
3135 ((ch
== 'e' || ch
== 'E') && b
== 10) ||
3136 ((ch
== 'p' || ch
== 'P') && (b
== 16 || b
== 2))) {
3138 /* NOTE: strtox should support that for hexa numbers, but
3139 non ISOC99 libcs do not support it, so we prefer to do
3141 /* hexadecimal or binary floats */
3142 /* XXX: handle overflows */
3154 } else if (t
>= 'a') {
3156 } else if (t
>= 'A') {
3161 bn_lshift(bn
, shift
, t
);
3168 if (t
>= 'a' && t
<= 'f') {
3170 } else if (t
>= 'A' && t
<= 'F') {
3172 } else if (t
>= '0' && t
<= '9') {
3178 error("invalid digit");
3179 bn_lshift(bn
, shift
, t
);
3184 if (ch
!= 'p' && ch
!= 'P')
3191 } else if (ch
== '-') {
3195 if (ch
< '0' || ch
> '9')
3196 expect("exponent digits");
3197 while (ch
>= '0' && ch
<= '9') {
3198 exp_val
= exp_val
* 10 + ch
- '0';
3201 exp_val
= exp_val
* s
;
3203 /* now we can generate the number */
3204 /* XXX: should patch directly float number */
3205 d
= (double)bn
[1] * 4294967296.0 + (double)bn
[0];
3206 d
= ldexp(d
, exp_val
- frac_bits
);
3211 /* float : should handle overflow */
3213 } else if (t
== 'L') {
3216 /* XXX: not large enough */
3217 tokc
.ld
= (long double)d
;
3223 /* decimal floats */
3225 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3230 while (ch
>= '0' && ch
<= '9') {
3231 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3237 if (ch
== 'e' || ch
== 'E') {
3238 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3242 if (ch
== '-' || ch
== '+') {
3243 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3248 if (ch
< '0' || ch
> '9')
3249 expect("exponent digits");
3250 while (ch
>= '0' && ch
<= '9') {
3251 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3263 tokc
.f
= strtof(token_buf
, NULL
);
3264 } else if (t
== 'L') {
3267 tokc
.ld
= strtold(token_buf
, NULL
);
3270 tokc
.d
= strtod(token_buf
, NULL
);
3274 unsigned long long n
, n1
;
3277 /* integer number */
3280 if (b
== 10 && *q
== '0') {
3287 /* no need for checks except for base 10 / 8 errors */
3290 } else if (t
>= 'a') {
3292 } else if (t
>= 'A') {
3297 error("invalid digit");
3301 /* detect overflow */
3302 /* XXX: this test is not reliable */
3304 error("integer constant overflow");
3307 /* XXX: not exactly ANSI compliant */
3308 if ((n
& 0xffffffff00000000LL
) != 0) {
3313 } else if (n
> 0x7fffffff) {
3324 error("three 'l's in integer constant");
3327 if (tok
== TOK_CINT
)
3329 else if (tok
== TOK_CUINT
)
3333 } else if (t
== 'U') {
3335 error("two 'u's in integer constant");
3337 if (tok
== TOK_CINT
)
3339 else if (tok
== TOK_CLLONG
)
3346 if (tok
== TOK_CINT
|| tok
== TOK_CUINT
)
3354 #define PARSE2(c1, tok1, c2, tok2) \
3365 /* return next token without macro substitution */
3366 static inline void next_nomacro1(void)
3386 /* first look if it is in fact an end of buffer */
3387 if (p
>= file
->buf_end
) {
3391 if (p
>= file
->buf_end
)
3404 TCCState
*s1
= tcc_state
;
3405 if (parse_flags
& PARSE_FLAG_LINEFEED
) {
3407 } else if (s1
->include_stack_ptr
== s1
->include_stack
||
3408 !(parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3409 /* no include left : end of file. */
3412 /* pop include file */
3414 /* test if previous '#endif' was after a #ifdef at
3416 if (tok_flags
& TOK_FLAG_ENDIF
) {
3418 printf("#endif %s\n", get_tok_str(file
->ifndef_macro_saved
, NULL
));
3420 add_cached_include(s1
, file
->inc_type
, file
->inc_filename
,
3421 file
->ifndef_macro_saved
);
3424 /* add end of include file debug info */
3426 put_stabd(N_EINCL
, 0, 0);
3428 /* pop include stack */
3430 s1
->include_stack_ptr
--;
3431 file
= *s1
->include_stack_ptr
;
3439 if (parse_flags
& PARSE_FLAG_LINEFEED
) {
3443 tok_flags
|= TOK_FLAG_BOL
;
3452 if ((tok_flags
& TOK_FLAG_BOL
) &&
3453 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3455 preprocess(tok_flags
& TOK_FLAG_BOF
);
3461 tok
= TOK_TWOSHARPS
;
3463 if (parse_flags
& PARSE_FLAG_ASM_COMMENTS
) {
3464 p
= parse_line_comment(p
- 1);
3473 case 'a': case 'b': case 'c': case 'd':
3474 case 'e': case 'f': case 'g': case 'h':
3475 case 'i': case 'j': case 'k': case 'l':
3476 case 'm': case 'n': case 'o': case 'p':
3477 case 'q': case 'r': case 's': case 't':
3478 case 'u': case 'v': case 'w': case 'x':
3480 case 'A': case 'B': case 'C': case 'D':
3481 case 'E': case 'F': case 'G': case 'H':
3482 case 'I': case 'J': case 'K':
3483 case 'M': case 'N': case 'O': case 'P':
3484 case 'Q': case 'R': case 'S': case 'T':
3485 case 'U': case 'V': case 'W': case 'X':
3491 h
= TOK_HASH_FUNC(h
, c
);
3495 if (!isidnum_table
[c
])
3497 h
= TOK_HASH_FUNC(h
, c
);
3504 /* fast case : no stray found, so we have the full token
3505 and we have already hashed it */
3507 h
&= (TOK_HASH_SIZE
- 1);
3508 pts
= &hash_ident
[h
];
3513 if (ts
->len
== len
&& !memcmp(ts
->str
, p1
, len
))
3515 pts
= &(ts
->hash_next
);
3517 ts
= tok_alloc_new(pts
, p1
, len
);
3521 cstr_reset(&tokcstr
);
3524 cstr_ccat(&tokcstr
, *p1
);
3530 while (isidnum_table
[c
]) {
3531 cstr_ccat(&tokcstr
, c
);
3534 ts
= tok_alloc(tokcstr
.data
, tokcstr
.size
);
3540 if (t
!= '\\' && t
!= '\'' && t
!= '\"') {
3542 goto parse_ident_fast
;
3545 if (c
== '\'' || c
== '\"') {
3549 cstr_reset(&tokcstr
);
3550 cstr_ccat(&tokcstr
, 'L');
3551 goto parse_ident_slow
;
3555 case '0': case '1': case '2': case '3':
3556 case '4': case '5': case '6': case '7':
3559 cstr_reset(&tokcstr
);
3560 /* after the first digit, accept digits, alpha, '.' or sign if
3561 prefixed by 'eEpP' */
3565 cstr_ccat(&tokcstr
, c
);
3567 if (!(isnum(c
) || isid(c
) || c
== '.' ||
3568 ((c
== '+' || c
== '-') &&
3569 (t
== 'e' || t
== 'E' || t
== 'p' || t
== 'P'))))
3572 /* We add a trailing '\0' to ease parsing */
3573 cstr_ccat(&tokcstr
, '\0');
3574 tokc
.cstr
= &tokcstr
;
3578 /* special dot handling because it can also start a number */
3581 cstr_reset(&tokcstr
);
3582 cstr_ccat(&tokcstr
, '.');
3584 } else if (c
== '.') {
3604 /* parse the string */
3606 p
= parse_pp_string(p
, sep
, &str
);
3607 cstr_ccat(&str
, '\0');
3609 /* eval the escape (should be done as TOK_PPNUM) */
3610 cstr_reset(&tokcstr
);
3611 parse_escape_string(&tokcstr
, str
.data
, is_long
);
3616 /* XXX: make it portable */
3620 char_size
= sizeof(int);
3621 if (tokcstr
.size
<= char_size
)
3622 error("empty character constant");
3623 if (tokcstr
.size
> 2 * char_size
)
3624 warning("multi-character character constant");
3626 tokc
.i
= *(int8_t *)tokcstr
.data
;
3629 tokc
.i
= *(int *)tokcstr
.data
;
3633 tokc
.cstr
= &tokcstr
;
3647 } else if (c
== '<') {
3665 } else if (c
== '>') {
3683 } else if (c
== '=') {
3696 } else if (c
== '=') {
3709 } else if (c
== '=') {
3722 } else if (c
== '=') {
3725 } else if (c
== '>') {
3733 PARSE2('!', '!', '=', TOK_NE
)
3734 PARSE2('=', '=', '=', TOK_EQ
)
3735 PARSE2('*', '*', '=', TOK_A_MUL
)
3736 PARSE2('%', '%', '=', TOK_A_MOD
)
3737 PARSE2('^', '^', '=', TOK_A_XOR
)
3739 /* comments or operator */
3743 p
= parse_comment(p
);
3745 } else if (c
== '/') {
3746 p
= parse_line_comment(p
);
3748 } else if (c
== '=') {
3768 case '$': /* only used in assembler */
3773 error("unrecognized character \\x%02x", c
);
3778 #if defined(PARSE_DEBUG)
3779 printf("token = %s\n", get_tok_str(tok
, &tokc
));
3783 /* return next token without macro substitution. Can read input from
3785 static void next_nomacro(void)
3791 TOK_GET(tok
, macro_ptr
, tokc
);
3792 if (tok
== TOK_LINENUM
) {
3793 file
->line_num
= tokc
.i
;
3802 /* substitute args in macro_str and return allocated string */
3803 static int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
3805 int *st
, last_tok
, t
, notfirst
;
3814 TOK_GET(t
, macro_str
, cval
);
3819 TOK_GET(t
, macro_str
, cval
);
3822 s
= sym_find2(args
, t
);
3829 cstr_ccat(&cstr
, ' ');
3830 TOK_GET(t
, st
, cval
);
3831 cstr_cat(&cstr
, get_tok_str(t
, &cval
));
3834 cstr_ccat(&cstr
, '\0');
3836 printf("stringize: %s\n", (char *)cstr
.data
);
3840 tok_str_add2(&str
, TOK_STR
, &cval
);
3843 tok_str_add2(&str
, t
, &cval
);
3845 } else if (t
>= TOK_IDENT
) {
3846 s
= sym_find2(args
, t
);
3849 /* if '##' is present before or after, no arg substitution */
3850 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
3851 /* special case for var arg macros : ## eats the
3852 ',' if empty VA_ARGS variable. */
3853 /* XXX: test of the ',' is not 100%
3854 reliable. should fix it to avoid security
3856 if (gnu_ext
&& s
->type
.t
&&
3857 last_tok
== TOK_TWOSHARPS
&&
3858 str
.len
>= 2 && str
.str
[str
.len
- 2] == ',') {
3860 /* suppress ',' '##' */
3863 /* suppress '##' and add variable */
3871 TOK_GET(t1
, st
, cval
);
3874 tok_str_add2(&str
, t1
, &cval
);
3878 /* NOTE: the stream cannot be read when macro
3879 substituing an argument */
3880 macro_subst(&str
, nested_list
, st
, 0);
3883 tok_str_add(&str
, t
);
3886 tok_str_add2(&str
, t
, &cval
);
3890 tok_str_add(&str
, 0);
3894 static char const ab_month_name
[12][4] =
3896 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
3897 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
3900 /* do macro substitution of current token with macro 's' and add
3901 result to (tok_str,tok_len). 'nested_list' is the list of all
3902 macros we got inside to avoid recursing. Return non zero if no
3903 substitution needs to be done */
3904 static int macro_subst_tok(TokenString
*tok_str
,
3905 Sym
**nested_list
, Sym
*s
, int can_read_stream
)
3907 Sym
*args
, *sa
, *sa1
;
3908 int mstr_allocated
, parlevel
, *mstr
, t
, t1
;
3915 /* if symbol is a macro, prepare substitution */
3916 /* special macros */
3917 if (tok
== TOK___LINE__
) {
3918 snprintf(buf
, sizeof(buf
), "%d", file
->line_num
);
3922 } else if (tok
== TOK___FILE__
) {
3923 cstrval
= file
->filename
;
3925 } else if (tok
== TOK___DATE__
|| tok
== TOK___TIME__
) {
3930 tm
= localtime(&ti
);
3931 if (tok
== TOK___DATE__
) {
3932 snprintf(buf
, sizeof(buf
), "%s %2d %d",
3933 ab_month_name
[tm
->tm_mon
], tm
->tm_mday
, tm
->tm_year
+ 1900);
3935 snprintf(buf
, sizeof(buf
), "%02d:%02d:%02d",
3936 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
);
3943 cstr_cat(&cstr
, cstrval
);
3944 cstr_ccat(&cstr
, '\0');
3946 tok_str_add2(tok_str
, t1
, &cval
);
3951 if (s
->type
.t
== MACRO_FUNC
) {
3952 /* NOTE: we do not use next_nomacro to avoid eating the
3953 next token. XXX: find better solution */
3956 if (t
== 0 && can_read_stream
) {
3957 /* end of macro stream: we must look at the token
3958 after in the file */
3964 /* XXX: incorrect with comments */
3965 ch
= file
->buf_ptr
[0];
3966 while (is_space(ch
) || ch
== '\n')
3970 if (t
!= '(') /* no macro subst */
3973 /* argument macro */
3978 /* NOTE: empty args are allowed, except if no args */
3980 /* handle '()' case */
3981 if (!args
&& !sa
&& tok
== ')')
3984 error("macro '%s' used with too many args",
3985 get_tok_str(s
->v
, 0));
3988 /* NOTE: non zero sa->t indicates VA_ARGS */
3989 while ((parlevel
> 0 ||
3991 (tok
!= ',' || sa
->type
.t
))) &&
3995 else if (tok
== ')')
3997 tok_str_add2(&str
, tok
, &tokc
);
4000 tok_str_add(&str
, 0);
4001 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, sa
->type
.t
, (int)str
.str
);
4004 /* special case for gcc var args: add an empty
4005 var arg argument if it is omitted */
4006 if (sa
&& sa
->type
.t
&& gnu_ext
)
4016 error("macro '%s' used with too few args",
4017 get_tok_str(s
->v
, 0));
4020 /* now subst each arg */
4021 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
4026 tok_str_free((int *)sa
->c
);
4032 sym_push2(nested_list
, s
->v
, 0, 0);
4033 macro_subst(tok_str
, nested_list
, mstr
, 1);
4034 /* pop nested defined symbol */
4036 *nested_list
= sa1
->prev
;
4044 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4045 return the resulting string (which must be freed). */
4046 static inline int *macro_twosharps(const int *macro_str
)
4049 const int *macro_ptr1
, *start_macro_ptr
, *ptr
, *saved_macro_ptr
;
4051 const char *p1
, *p2
;
4053 TokenString macro_str1
;
4056 start_macro_ptr
= macro_str
;
4057 /* we search the first '##' */
4059 macro_ptr1
= macro_str
;
4060 TOK_GET(t
, macro_str
, cval
);
4061 /* nothing more to do if end of string */
4064 if (*macro_str
== TOK_TWOSHARPS
)
4068 /* we saw '##', so we need more processing to handle it */
4070 tok_str_new(¯o_str1
);
4074 /* add all tokens seen so far */
4075 for(ptr
= start_macro_ptr
; ptr
< macro_ptr1
;) {
4076 TOK_GET(t
, ptr
, cval
);
4077 tok_str_add2(¯o_str1
, t
, &cval
);
4079 saved_macro_ptr
= macro_ptr
;
4080 /* XXX: get rid of the use of macro_ptr here */
4081 macro_ptr
= (int *)macro_str
;
4083 while (*macro_ptr
== TOK_TWOSHARPS
) {
4085 macro_ptr1
= macro_ptr
;
4088 TOK_GET(t
, macro_ptr
, cval
);
4089 /* We concatenate the two tokens if we have an
4090 identifier or a preprocessing number */
4092 p1
= get_tok_str(tok
, &tokc
);
4093 cstr_cat(&cstr
, p1
);
4094 p2
= get_tok_str(t
, &cval
);
4095 cstr_cat(&cstr
, p2
);
4096 cstr_ccat(&cstr
, '\0');
4098 if ((tok
>= TOK_IDENT
|| tok
== TOK_PPNUM
) &&
4099 (t
>= TOK_IDENT
|| t
== TOK_PPNUM
)) {
4100 if (tok
== TOK_PPNUM
) {
4101 /* if number, then create a number token */
4102 /* NOTE: no need to allocate because
4103 tok_str_add2() does it */
4106 /* if identifier, we must do a test to
4107 validate we have a correct identifier */
4108 if (t
== TOK_PPNUM
) {
4118 if (!isnum(c
) && !isid(c
))
4122 ts
= tok_alloc(cstr
.data
, strlen(cstr
.data
));
4123 tok
= ts
->tok
; /* modify current token */
4126 const char *str
= cstr
.data
;
4127 const unsigned char *q
;
4129 /* we look for a valid token */
4130 /* XXX: do more extensive checks */
4131 if (!strcmp(str
, ">>=")) {
4133 } else if (!strcmp(str
, "<<=")) {
4135 } else if (strlen(str
) == 2) {
4136 /* search in two bytes table */
4141 if (q
[0] == str
[0] && q
[1] == str
[1])
4148 /* NOTE: because get_tok_str use a static buffer,
4151 p1
= get_tok_str(tok
, &tokc
);
4152 cstr_cat(&cstr
, p1
);
4153 cstr_ccat(&cstr
, '\0');
4154 p2
= get_tok_str(t
, &cval
);
4155 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr
.data
, p2
);
4156 /* cannot merge tokens: just add them separately */
4157 tok_str_add2(¯o_str1
, tok
, &tokc
);
4158 /* XXX: free associated memory ? */
4165 tok_str_add2(¯o_str1
, tok
, &tokc
);
4170 macro_ptr
= (int *)saved_macro_ptr
;
4172 tok_str_add(¯o_str1
, 0);
4173 return macro_str1
.str
;
4177 /* do macro substitution of macro_str and add result to
4178 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4179 inside to avoid recursing. */
4180 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
4181 const int *macro_str
, int can_read_stream
)
4184 int *saved_macro_ptr
, *macro_str1
;
4189 /* first scan for '##' operator handling */
4191 macro_str1
= macro_twosharps(ptr
);
4195 /* NOTE: ptr == NULL can only happen if tokens are read from
4196 file stream due to a macro function call */
4199 TOK_GET(t
, ptr
, cval
);
4204 /* if nested substitution, do nothing */
4205 if (sym_find2(*nested_list
, t
))
4207 saved_macro_ptr
= macro_ptr
;
4208 macro_ptr
= (int *)ptr
;
4210 ret
= macro_subst_tok(tok_str
, nested_list
, s
, can_read_stream
);
4211 ptr
= (int *)macro_ptr
;
4212 macro_ptr
= saved_macro_ptr
;
4217 tok_str_add2(tok_str
, t
, &cval
);
4221 tok_str_free(macro_str1
);
4224 /* return next token with macro substitution */
4225 static void next(void)
4227 Sym
*nested_list
, *s
;
4233 /* if not reading from macro substituted string, then try
4234 to substitute macros */
4235 if (tok
>= TOK_IDENT
&&
4236 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
4237 s
= define_find(tok
);
4239 /* we have a macro: we try to substitute */
4242 if (macro_subst_tok(&str
, &nested_list
, s
, 1) == 0) {
4243 /* substitution done, NOTE: maybe empty */
4244 tok_str_add(&str
, 0);
4245 macro_ptr
= str
.str
;
4246 macro_ptr_allocated
= str
.str
;
4253 /* end of macro or end of unget buffer */
4254 if (unget_buffer_enabled
) {
4255 macro_ptr
= unget_saved_macro_ptr
;
4256 unget_buffer_enabled
= 0;
4258 /* end of macro string: free it */
4259 tok_str_free(macro_ptr_allocated
);
4266 /* convert preprocessor tokens into C tokens */
4267 if (tok
== TOK_PPNUM
&&
4268 (parse_flags
& PARSE_FLAG_TOK_NUM
)) {
4269 parse_number((char *)tokc
.cstr
->data
);
4273 /* push back current token and set current token to 'last_tok'. Only
4274 identifier case handled for labels. */
4275 static inline void unget_tok(int last_tok
)
4279 unget_saved_macro_ptr
= macro_ptr
;
4280 unget_buffer_enabled
= 1;
4281 q
= unget_saved_buffer
;
4284 n
= tok_ext_size(tok
) - 1;
4287 *q
= 0; /* end of token string */
4292 void swap(int *p
, int *q
)
4300 void vsetc(CType
*type
, int r
, CValue
*vc
)
4304 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4305 error("memory full");
4306 /* cannot let cpu flags if other instruction are generated. Also
4307 avoid leaving VT_JMP anywhere except on the top of the stack
4308 because it would complicate the code generator. */
4309 if (vtop
>= vstack
) {
4310 v
= vtop
->r
& VT_VALMASK
;
4311 if (v
== VT_CMP
|| (v
& ~1) == VT_JMP
)
4317 vtop
->r2
= VT_CONST
;
4321 /* push integer constant */
4326 vsetc(&int_type
, VT_CONST
, &cval
);
4329 /* Return a static symbol pointing to a section */
4330 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
4331 unsigned long offset
, unsigned long size
)
4337 sym
= global_identifier_push(v
, type
->t
| VT_STATIC
, 0);
4338 sym
->type
.ref
= type
->ref
;
4339 sym
->r
= VT_CONST
| VT_SYM
;
4340 put_extern_sym(sym
, sec
, offset
, size
);
4344 /* push a reference to a section offset by adding a dummy symbol */
4345 static void vpush_ref(CType
*type
, Section
*sec
, unsigned long offset
, unsigned long size
)
4350 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4351 vtop
->sym
= get_sym_ref(type
, sec
, offset
, size
);
4354 /* define a new external reference to a symbol 'v' of type 'u' */
4355 static Sym
*external_global_sym(int v
, CType
*type
, int r
)
4361 /* push forward reference */
4362 s
= global_identifier_push(v
, type
->t
| VT_EXTERN
, 0);
4363 s
->type
.ref
= type
->ref
;
4364 s
->r
= r
| VT_CONST
| VT_SYM
;
4369 /* define a new external reference to a symbol 'v' of type 'u' */
4370 static Sym
*external_sym(int v
, CType
*type
, int r
)
4376 /* push forward reference */
4377 s
= sym_push(v
, type
, r
| VT_CONST
| VT_SYM
, 0);
4378 s
->type
.t
|= VT_EXTERN
;
4380 if (!is_compatible_types(&s
->type
, type
))
4381 error("incompatible types for redefinition of '%s'",
4382 get_tok_str(v
, NULL
));
4387 /* push a reference to global symbol v */
4388 static void vpush_global_sym(CType
*type
, int v
)
4393 sym
= external_global_sym(v
, type
, 0);
4395 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4399 void vset(CType
*type
, int r
, int v
)
4404 vsetc(type
, r
, &cval
);
4407 void vseti(int r
, int v
)
4423 void vpushv(SValue
*v
)
4425 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4426 error("memory full");
4436 /* save r to the memory stack, and mark it as being free */
4437 void save_reg(int r
)
4439 int l
, saved
, size
, align
;
4443 /* modify all stack values */
4446 for(p
=vstack
;p
<=vtop
;p
++) {
4447 if ((p
->r
& VT_VALMASK
) == r
||
4448 (p
->r2
& VT_VALMASK
) == r
) {
4449 /* must save value on stack if not already done */
4451 /* NOTE: must reload 'r' because r might be equal to r2 */
4452 r
= p
->r
& VT_VALMASK
;
4453 /* store register in the stack */
4455 if ((p
->r
& VT_LVAL
) ||
4456 (!is_float(type
->t
) && (type
->t
& VT_BTYPE
) != VT_LLONG
))
4458 size
= type_size(type
, &align
);
4459 loc
= (loc
- size
) & -align
;
4460 sv
.type
.t
= type
->t
;
4461 sv
.r
= VT_LOCAL
| VT_LVAL
;
4464 #ifdef TCC_TARGET_I386
4465 /* x86 specific: need to pop fp register ST0 if saved */
4466 if (r
== TREG_ST0
) {
4467 o(0xd9dd); /* fstp %st(1) */
4470 /* special long long case */
4471 if ((type
->t
& VT_BTYPE
) == VT_LLONG
) {
4478 /* mark that stack entry as being saved on the stack */
4479 if (p
->r
& VT_LVAL
) {
4480 /* also clear the bounded flag because the
4481 relocation address of the function was stored in
4483 p
->r
= (p
->r
& ~(VT_VALMASK
| VT_BOUNDED
)) | VT_LLOCAL
;
4485 p
->r
= lvalue_type(p
->type
.t
) | VT_LOCAL
;
4493 /* find a register of class 'rc2' with at most one reference on stack.
4494 * If none, call get_reg(rc) */
4495 int get_reg_ex(int rc
, int rc2
)
4500 for(r
=0;r
<NB_REGS
;r
++) {
4501 if (reg_classes
[r
] & rc2
) {
4504 for(p
= vstack
; p
<= vtop
; p
++) {
4505 if ((p
->r
& VT_VALMASK
) == r
||
4506 (p
->r2
& VT_VALMASK
) == r
)
4516 /* find a free register of class 'rc'. If none, save one register */
4522 /* find a free register */
4523 for(r
=0;r
<NB_REGS
;r
++) {
4524 if (reg_classes
[r
] & rc
) {
4525 for(p
=vstack
;p
<=vtop
;p
++) {
4526 if ((p
->r
& VT_VALMASK
) == r
||
4527 (p
->r2
& VT_VALMASK
) == r
)
4535 /* no register left : free the first one on the stack (VERY
4536 IMPORTANT to start from the bottom to ensure that we don't
4537 spill registers used in gen_opi()) */
4538 for(p
=vstack
;p
<=vtop
;p
++) {
4539 r
= p
->r
& VT_VALMASK
;
4540 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
))
4542 /* also look at second register (if long long) */
4543 r
= p
->r2
& VT_VALMASK
;
4544 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
4550 /* Should never comes here */
4554 /* save registers up to (vtop - n) stack entry */
4555 void save_regs(int n
)
4560 for(p
= vstack
;p
<= p1
; p
++) {
4561 r
= p
->r
& VT_VALMASK
;
4568 /* move register 's' to 'r', and flush previous value of r to memory
4570 void move_reg(int r
, int s
)
4583 /* get address of vtop (vtop MUST BE an lvalue) */
4586 vtop
->r
&= ~VT_LVAL
;
4587 /* tricky: if saved lvalue, then we can go back to lvalue */
4588 if ((vtop
->r
& VT_VALMASK
) == VT_LLOCAL
)
4589 vtop
->r
= (vtop
->r
& ~(VT_VALMASK
| VT_LVAL_TYPE
)) | VT_LOCAL
| VT_LVAL
;
4592 #ifdef CONFIG_TCC_BCHECK
4593 /* generate lvalue bound code */
4599 vtop
->r
&= ~VT_MUSTBOUND
;
4600 /* if lvalue, then use checking code before dereferencing */
4601 if (vtop
->r
& VT_LVAL
) {
4602 /* if not VT_BOUNDED value, then make one */
4603 if (!(vtop
->r
& VT_BOUNDED
)) {
4604 lval_type
= vtop
->r
& (VT_LVAL_TYPE
| VT_LVAL
);
4605 /* must save type because we must set it to int to get pointer */
4607 vtop
->type
.t
= VT_INT
;
4610 gen_bounded_ptr_add();
4611 vtop
->r
|= lval_type
;
4614 /* then check for dereferencing */
4615 gen_bounded_ptr_deref();
4620 /* store vtop a register belonging to class 'rc'. lvalues are
4621 converted to values. Cannot be used if cannot be converted to
4622 register value (such as structures). */
4625 int r
, r2
, rc2
, bit_pos
, bit_size
, size
, align
, i
;
4626 unsigned long long ll
;
4628 /* NOTE: get_reg can modify vstack[] */
4629 if (vtop
->type
.t
& VT_BITFIELD
) {
4630 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
4631 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
4632 /* remove bit field info to avoid loops */
4633 vtop
->type
.t
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
4634 /* generate shifts */
4635 vpushi(32 - (bit_pos
+ bit_size
));
4637 vpushi(32 - bit_size
);
4638 /* NOTE: transformed to SHR if unsigned */
4642 if (is_float(vtop
->type
.t
) &&
4643 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4646 unsigned long offset
;
4648 /* XXX: unify with initializers handling ? */
4649 /* CPUs usually cannot use float constants, so we store them
4650 generically in data segment */
4651 size
= type_size(&vtop
->type
, &align
);
4652 offset
= (data_section
->data_offset
+ align
- 1) & -align
;
4653 data_section
->data_offset
= offset
;
4654 /* XXX: not portable yet */
4655 ptr
= section_ptr_add(data_section
, size
);
4658 ptr
[i
] = vtop
->c
.tab
[i
];
4659 sym
= get_sym_ref(&vtop
->type
, data_section
, offset
, size
<< 2);
4660 vtop
->r
|= VT_LVAL
| VT_SYM
;
4664 #ifdef CONFIG_TCC_BCHECK
4665 if (vtop
->r
& VT_MUSTBOUND
)
4669 r
= vtop
->r
& VT_VALMASK
;
4670 /* need to reload if:
4672 - lvalue (need to dereference pointer)
4673 - already a register, but not in the right class */
4674 if (r
>= VT_CONST
||
4675 (vtop
->r
& VT_LVAL
) ||
4676 !(reg_classes
[r
] & rc
) ||
4677 ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
&&
4678 !(reg_classes
[vtop
->r2
] & rc
))) {
4680 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
4681 /* two register type load : expand to two words
4683 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4686 vtop
->c
.ui
= ll
; /* first word */
4688 vtop
->r
= r
; /* save register value */
4689 vpushi(ll
>> 32); /* second word */
4690 } else if (r
>= VT_CONST
|| /* XXX: test to VT_CONST incorrect ? */
4691 (vtop
->r
& VT_LVAL
)) {
4692 /* We do not want to modifier the long long
4693 pointer here, so the safest (and less
4694 efficient) is to save all the other registers
4695 in the stack. XXX: totally inefficient. */
4697 /* load from memory */
4700 vtop
[-1].r
= r
; /* save register value */
4701 /* increment pointer to get second word */
4702 vtop
->type
.t
= VT_INT
;
4708 /* move registers */
4711 vtop
[-1].r
= r
; /* save register value */
4712 vtop
->r
= vtop
[-1].r2
;
4714 /* allocate second register */
4721 /* write second register */
4723 } else if ((vtop
->r
& VT_LVAL
) && !is_float(vtop
->type
.t
)) {
4725 /* lvalue of scalar type : need to use lvalue type
4726 because of possible cast */
4729 /* compute memory access type */
4730 if (vtop
->r
& VT_LVAL_BYTE
)
4732 else if (vtop
->r
& VT_LVAL_SHORT
)
4734 if (vtop
->r
& VT_LVAL_UNSIGNED
)
4738 /* restore wanted type */
4741 /* one register type load */
4746 #ifdef TCC_TARGET_C67
4747 /* uses register pairs for doubles */
4748 if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
)
4755 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4756 void gv2(int rc1
, int rc2
)
4760 /* generate more generic register first. But VT_JMP or VT_CMP
4761 values must be generated first in all cases to avoid possible
4763 v
= vtop
[0].r
& VT_VALMASK
;
4764 if (v
!= VT_CMP
&& (v
& ~1) != VT_JMP
&& rc1
<= rc2
) {
4769 /* test if reload is needed for first register */
4770 if ((vtop
[-1].r
& VT_VALMASK
) >= VT_CONST
) {
4780 /* test if reload is needed for first register */
4781 if ((vtop
[0].r
& VT_VALMASK
) >= VT_CONST
) {
4787 /* expand long long on stack in two int registers */
4792 u
= vtop
->type
.t
& VT_UNSIGNED
;
4795 vtop
[0].r
= vtop
[-1].r2
;
4796 vtop
[0].r2
= VT_CONST
;
4797 vtop
[-1].r2
= VT_CONST
;
4798 vtop
[0].type
.t
= VT_INT
| u
;
4799 vtop
[-1].type
.t
= VT_INT
| u
;
4802 #ifdef TCC_TARGET_ARM
4803 /* expand long long on stack */
4804 void lexpand_nr(void)
4808 u
= vtop
->type
.t
& VT_UNSIGNED
;
4810 vtop
->r2
= VT_CONST
;
4811 vtop
->type
.t
= VT_INT
| u
;
4812 v
=vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
);
4813 if (v
== VT_CONST
) {
4814 vtop
[-1].c
.ui
= vtop
->c
.ull
;
4815 vtop
->c
.ui
= vtop
->c
.ull
>> 32;
4817 } else if (v
== (VT_LVAL
|VT_CONST
) || v
== (VT_LVAL
|VT_LOCAL
)) {
4819 vtop
->r
= vtop
[-1].r
;
4820 } else if (v
> VT_CONST
) {
4824 vtop
->r
= vtop
[-1].r2
;
4825 vtop
[-1].r2
= VT_CONST
;
4826 vtop
[-1].type
.t
= VT_INT
| u
;
4830 /* build a long long from two ints */
4833 gv2(RC_INT
, RC_INT
);
4834 vtop
[-1].r2
= vtop
[0].r
;
4835 vtop
[-1].type
.t
= t
;
4839 /* rotate n first stack elements to the bottom
4840 I1 ... In -> I2 ... In I1 [top is right]
4848 for(i
=-n
+1;i
!=0;i
++)
4849 vtop
[i
] = vtop
[i
+1];
4853 /* rotate n first stack elements to the top
4854 I1 ... In -> In I1 ... I(n-1) [top is right]
4862 for(i
= 0;i
< n
- 1; i
++)
4863 vtop
[-i
] = vtop
[-i
- 1];
4867 #ifdef TCC_TARGET_ARM
4868 /* like vrott but in other direction
4869 In ... I1 -> I(n-1) ... I1 In [top is right]
4877 for(i
= n
- 1; i
> 0; i
--)
4878 vtop
[-i
] = vtop
[-i
+ 1];
4883 /* pop stack value */
4887 v
= vtop
->r
& VT_VALMASK
;
4888 #ifdef TCC_TARGET_I386
4889 /* for x86, we need to pop the FP stack */
4890 if (v
== TREG_ST0
&& !nocode_wanted
) {
4891 o(0xd9dd); /* fstp %st(1) */
4894 if (v
== VT_JMP
|| v
== VT_JMPI
) {
4895 /* need to put correct jump if && or || without test */
4901 /* convert stack entry to register and duplicate its value in another
4909 if ((t
& VT_BTYPE
) == VT_LLONG
) {
4916 /* stack: H L L1 H1 */
4924 /* duplicate value */
4935 load(r1
, &sv
); /* move r to r1 */
4937 /* duplicates value */
4942 /* generate CPU independent (unsigned) long long operations */
4943 void gen_opl(int op
)
4945 int t
, a
, b
, op1
, c
, i
;
4952 func
= TOK___divdi3
;
4955 func
= TOK___udivdi3
;
4958 func
= TOK___moddi3
;
4961 func
= TOK___umoddi3
;
4963 /* call generic long long function */
4964 vpush_global_sym(&func_old_type
, func
);
4969 vtop
->r2
= REG_LRET
;
4982 /* stack: L1 H1 L2 H2 */
4987 vtop
[-2] = vtop
[-3];
4990 /* stack: H1 H2 L1 L2 */
4996 /* stack: H1 H2 L1 L2 ML MH */
4999 /* stack: ML MH H1 H2 L1 L2 */
5003 /* stack: ML MH H1 L2 H2 L1 */
5008 /* stack: ML MH M1 M2 */
5011 } else if (op
== '+' || op
== '-') {
5012 /* XXX: add non carry method too (for MIPS or alpha) */
5018 /* stack: H1 H2 (L1 op L2) */
5021 gen_op(op1
+ 1); /* TOK_xxxC2 */
5024 /* stack: H1 H2 (L1 op L2) */
5027 /* stack: (L1 op L2) H1 H2 */
5029 /* stack: (L1 op L2) (H1 op H2) */
5037 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
5038 t
= vtop
[-1].type
.t
;
5042 /* stack: L H shift */
5044 /* constant: simpler */
5045 /* NOTE: all comments are for SHL. the other cases are
5046 done by swaping words */
5057 if (op
!= TOK_SAR
) {
5090 /* XXX: should provide a faster fallback on x86 ? */
5093 func
= TOK___sardi3
;
5096 func
= TOK___shrdi3
;
5099 func
= TOK___shldi3
;
5105 /* compare operations */
5111 /* stack: L1 H1 L2 H2 */
5113 vtop
[-1] = vtop
[-2];
5115 /* stack: L1 L2 H1 H2 */
5118 /* when values are equal, we need to compare low words. since
5119 the jump is inverted, we invert the test too. */
5122 else if (op1
== TOK_GT
)
5124 else if (op1
== TOK_ULT
)
5126 else if (op1
== TOK_UGT
)
5131 if (op1
!= TOK_NE
) {
5135 /* generate non equal test */
5136 /* XXX: NOT PORTABLE yet */
5140 #if defined(TCC_TARGET_I386)
5141 b
= psym(0x850f, 0);
5142 #elif defined(TCC_TARGET_ARM)
5144 o(0x1A000000 | encbranch(ind
, 0, 1));
5145 #elif defined(TCC_TARGET_C67)
5146 error("not implemented");
5148 #error not supported
5152 /* compare low. Always unsigned */
5156 else if (op1
== TOK_LE
)
5158 else if (op1
== TOK_GT
)
5160 else if (op1
== TOK_GE
)
5170 /* handle integer constant optimizations and various machine
5172 void gen_opic(int op
)
5179 /* currently, we cannot do computations with forward symbols */
5180 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5181 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5185 case '+': v1
->c
.i
+= fc
; break;
5186 case '-': v1
->c
.i
-= fc
; break;
5187 case '&': v1
->c
.i
&= fc
; break;
5188 case '^': v1
->c
.i
^= fc
; break;
5189 case '|': v1
->c
.i
|= fc
; break;
5190 case '*': v1
->c
.i
*= fc
; break;
5197 /* if division by zero, generate explicit division */
5200 error("division by zero in constant");
5204 default: v1
->c
.i
/= fc
; break;
5205 case '%': v1
->c
.i
%= fc
; break;
5206 case TOK_UDIV
: v1
->c
.i
= (unsigned)v1
->c
.i
/ fc
; break;
5207 case TOK_UMOD
: v1
->c
.i
= (unsigned)v1
->c
.i
% fc
; break;
5210 case TOK_SHL
: v1
->c
.i
<<= fc
; break;
5211 case TOK_SHR
: v1
->c
.i
= (unsigned)v1
->c
.i
>> fc
; break;
5212 case TOK_SAR
: v1
->c
.i
>>= fc
; break;
5214 case TOK_ULT
: v1
->c
.i
= (unsigned)v1
->c
.i
< (unsigned)fc
; break;
5215 case TOK_UGE
: v1
->c
.i
= (unsigned)v1
->c
.i
>= (unsigned)fc
; break;
5216 case TOK_EQ
: v1
->c
.i
= v1
->c
.i
== fc
; break;
5217 case TOK_NE
: v1
->c
.i
= v1
->c
.i
!= fc
; break;
5218 case TOK_ULE
: v1
->c
.i
= (unsigned)v1
->c
.i
<= (unsigned)fc
; break;
5219 case TOK_UGT
: v1
->c
.i
= (unsigned)v1
->c
.i
> (unsigned)fc
; break;
5220 case TOK_LT
: v1
->c
.i
= v1
->c
.i
< fc
; break;
5221 case TOK_GE
: v1
->c
.i
= v1
->c
.i
>= fc
; break;
5222 case TOK_LE
: v1
->c
.i
= v1
->c
.i
<= fc
; break;
5223 case TOK_GT
: v1
->c
.i
= v1
->c
.i
> fc
; break;
5225 case TOK_LAND
: v1
->c
.i
= v1
->c
.i
&& fc
; break;
5226 case TOK_LOR
: v1
->c
.i
= v1
->c
.i
|| fc
; break;
5232 /* if commutative ops, put c2 as constant */
5233 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
5234 op
== '|' || op
== '*')) {
5239 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
5242 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
5243 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
5249 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
5250 /* try to use shifts instead of muls or divs */
5251 if (fc
> 0 && (fc
& (fc
- 1)) == 0) {
5260 else if (op
== TOK_PDIV
)
5266 } else if (c2
&& (op
== '+' || op
== '-') &&
5267 (vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) ==
5268 (VT_CONST
| VT_SYM
)) {
5269 /* symbol + constant case */
5276 if (!nocode_wanted
) {
5277 /* call low level op generator */
5286 /* generate a floating point operation with constant propagation */
5287 void gen_opif(int op
)
5295 /* currently, we cannot do computations with forward symbols */
5296 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5297 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5299 if (v1
->type
.t
== VT_FLOAT
) {
5302 } else if (v1
->type
.t
== VT_DOUBLE
) {
5310 /* NOTE: we only do constant propagation if finite number (not
5311 NaN or infinity) (ANSI spec) */
5312 if (!ieee_finite(f1
) || !ieee_finite(f2
))
5316 case '+': f1
+= f2
; break;
5317 case '-': f1
-= f2
; break;
5318 case '*': f1
*= f2
; break;
5322 error("division by zero in constant");
5327 /* XXX: also handles tests ? */
5331 /* XXX: overflow test ? */
5332 if (v1
->type
.t
== VT_FLOAT
) {
5334 } else if (v1
->type
.t
== VT_DOUBLE
) {
5342 if (!nocode_wanted
) {
5350 static int pointed_size(CType
*type
)
5353 return type_size(pointed_type(type
), &align
);
5356 static inline int is_null_pointer(SValue
*p
)
5358 if ((p
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
5360 return ((p
->type
.t
& VT_BTYPE
) == VT_INT
&& p
->c
.i
== 0) ||
5361 ((p
->type
.t
& VT_BTYPE
) == VT_LLONG
&& p
->c
.ll
== 0);
5364 static inline int is_integer_btype(int bt
)
5366 return (bt
== VT_BYTE
|| bt
== VT_SHORT
||
5367 bt
== VT_INT
|| bt
== VT_LLONG
);
5370 /* check types for comparison or substraction of pointers */
5371 static void check_comparison_pointer_types(SValue
*p1
, SValue
*p2
, int op
)
5373 CType
*type1
, *type2
, tmp_type1
, tmp_type2
;
5376 /* null pointers are accepted for all comparisons as gcc */
5377 if (is_null_pointer(p1
) || is_null_pointer(p2
))
5381 bt1
= type1
->t
& VT_BTYPE
;
5382 bt2
= type2
->t
& VT_BTYPE
;
5383 /* accept comparison between pointer and integer with a warning */
5384 if ((is_integer_btype(bt1
) || is_integer_btype(bt2
)) && op
!= '-') {
5385 warning("comparison between pointer and integer");
5389 /* both must be pointers or implicit function pointers */
5390 if (bt1
== VT_PTR
) {
5391 type1
= pointed_type(type1
);
5392 } else if (bt1
!= VT_FUNC
)
5393 goto invalid_operands
;
5395 if (bt2
== VT_PTR
) {
5396 type2
= pointed_type(type2
);
5397 } else if (bt2
!= VT_FUNC
) {
5399 error("invalid operands to binary %s", get_tok_str(op
, NULL
));
5401 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
5402 (type2
->t
& VT_BTYPE
) == VT_VOID
)
5406 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5407 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5408 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
5409 /* gcc-like error if '-' is used */
5411 goto invalid_operands
;
5413 warning("comparison of distinct pointer types lacks a cast");
5417 /* generic gen_op: handles types problems */
5420 int u
, t1
, t2
, bt1
, bt2
, t
;
5423 t1
= vtop
[-1].type
.t
;
5424 t2
= vtop
[0].type
.t
;
5425 bt1
= t1
& VT_BTYPE
;
5426 bt2
= t2
& VT_BTYPE
;
5428 if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
5429 /* at least one operand is a pointer */
5430 /* relationnal op: must be both pointers */
5431 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
5432 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5433 /* pointers are handled are unsigned */
5434 t
= VT_INT
| VT_UNSIGNED
;
5437 /* if both pointers, then it must be the '-' op */
5438 if (bt1
== VT_PTR
&& bt2
== VT_PTR
) {
5440 error("cannot use pointers here");
5441 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5442 /* XXX: check that types are compatible */
5443 u
= pointed_size(&vtop
[-1].type
);
5445 /* set to integer type */
5446 vtop
->type
.t
= VT_INT
;
5450 /* exactly one pointer : must be '+' or '-'. */
5451 if (op
!= '-' && op
!= '+')
5452 error("cannot use pointers here");
5453 /* Put pointer as first operand */
5454 if (bt2
== VT_PTR
) {
5458 type1
= vtop
[-1].type
;
5459 /* XXX: cast to int ? (long long case) */
5460 vpushi(pointed_size(&vtop
[-1].type
));
5462 #ifdef CONFIG_TCC_BCHECK
5463 /* if evaluating constant expression, no code should be
5464 generated, so no bound check */
5465 if (do_bounds_check
&& !const_wanted
) {
5466 /* if bounded pointers, we generate a special code to
5473 gen_bounded_ptr_add();
5479 /* put again type if gen_opic() swaped operands */
5482 } else if (is_float(bt1
) || is_float(bt2
)) {
5483 /* compute bigger type and do implicit casts */
5484 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
5486 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
5491 /* floats can only be used for a few operations */
5492 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
5493 (op
< TOK_ULT
|| op
> TOK_GT
))
5494 error("invalid operands for binary operation");
5496 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
5497 /* cast to biggest op */
5499 /* convert to unsigned if it does not fit in a long long */
5500 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
5501 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
5505 /* integer operations */
5507 /* convert to unsigned if it does not fit in an integer */
5508 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
5509 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
5512 /* XXX: currently, some unsigned operations are explicit, so
5513 we modify them here */
5514 if (t
& VT_UNSIGNED
) {
5521 else if (op
== TOK_LT
)
5523 else if (op
== TOK_GT
)
5525 else if (op
== TOK_LE
)
5527 else if (op
== TOK_GE
)
5534 /* special case for shifts and long long: we keep the shift as
5536 if (op
== TOK_SHR
|| op
== TOK_SAR
|| op
== TOK_SHL
)
5541 else if ((t
& VT_BTYPE
) == VT_LLONG
)
5545 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
5546 /* relationnal op: the result is an int */
5547 vtop
->type
.t
= VT_INT
;
5554 /* generic itof for unsigned long long case */
5555 void gen_cvt_itof1(int t
)
5557 if ((vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
)) ==
5558 (VT_LLONG
| VT_UNSIGNED
)) {
5561 vpush_global_sym(&func_old_type
, TOK___ulltof
);
5562 else if (t
== VT_DOUBLE
)
5563 vpush_global_sym(&func_old_type
, TOK___ulltod
);
5565 vpush_global_sym(&func_old_type
, TOK___ulltold
);
5575 /* generic ftoi for unsigned long long case */
5576 void gen_cvt_ftoi1(int t
)
5580 if (t
== (VT_LLONG
| VT_UNSIGNED
)) {
5581 /* not handled natively */
5582 st
= vtop
->type
.t
& VT_BTYPE
;
5584 vpush_global_sym(&func_old_type
, TOK___fixunssfdi
);
5585 else if (st
== VT_DOUBLE
)
5586 vpush_global_sym(&func_old_type
, TOK___fixunsdfdi
);
5588 vpush_global_sym(&func_old_type
, TOK___fixunsxfdi
);
5593 vtop
->r2
= REG_LRET
;
5599 /* force char or short cast */
5600 void force_charshort_cast(int t
)
5604 /* XXX: add optimization if lvalue : just change type and offset */
5609 if (t
& VT_UNSIGNED
) {
5610 vpushi((1 << bits
) - 1);
5621 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5622 static void gen_cast(CType
*type
)
5624 int sbt
, dbt
, sf
, df
, c
;
5626 /* special delayed cast for char/short */
5627 /* XXX: in some cases (multiple cascaded casts), it may still
5629 if (vtop
->r
& VT_MUSTCAST
) {
5630 vtop
->r
&= ~VT_MUSTCAST
;
5631 force_charshort_cast(vtop
->type
.t
);
5634 /* bitfields first get cast to ints */
5635 if (vtop
->type
.t
& VT_BITFIELD
) {
5639 dbt
= type
->t
& (VT_BTYPE
| VT_UNSIGNED
);
5640 sbt
= vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
);
5642 if (sbt
!= dbt
&& !nocode_wanted
) {
5645 c
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5647 /* convert from fp to fp */
5649 /* constant case: we can do it now */
5650 /* XXX: in ISOC, cannot do it if error in convert */
5651 if (dbt
== VT_FLOAT
&& sbt
== VT_DOUBLE
)
5652 vtop
->c
.f
= (float)vtop
->c
.d
;
5653 else if (dbt
== VT_FLOAT
&& sbt
== VT_LDOUBLE
)
5654 vtop
->c
.f
= (float)vtop
->c
.ld
;
5655 else if (dbt
== VT_DOUBLE
&& sbt
== VT_FLOAT
)
5656 vtop
->c
.d
= (double)vtop
->c
.f
;
5657 else if (dbt
== VT_DOUBLE
&& sbt
== VT_LDOUBLE
)
5658 vtop
->c
.d
= (double)vtop
->c
.ld
;
5659 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_FLOAT
)
5660 vtop
->c
.ld
= (long double)vtop
->c
.f
;
5661 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_DOUBLE
)
5662 vtop
->c
.ld
= (long double)vtop
->c
.d
;
5664 /* non constant case: generate code */
5668 /* convert int to fp */
5671 case VT_LLONG
| VT_UNSIGNED
:
5673 /* XXX: add const cases for long long */
5675 case VT_INT
| VT_UNSIGNED
:
5677 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.ui
; break;
5678 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.ui
; break;
5679 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.ui
; break;
5684 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.i
; break;
5685 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.i
; break;
5686 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.i
; break;
5692 #if !defined(TCC_TARGET_ARM)
5699 /* convert fp to int */
5700 /* we handle char/short/etc... with generic code */
5701 if (dbt
!= (VT_INT
| VT_UNSIGNED
) &&
5702 dbt
!= (VT_LLONG
| VT_UNSIGNED
) &&
5707 case VT_LLONG
| VT_UNSIGNED
:
5709 /* XXX: add const cases for long long */
5711 case VT_INT
| VT_UNSIGNED
:
5713 case VT_FLOAT
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5714 case VT_DOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5715 case VT_LDOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5721 case VT_FLOAT
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5722 case VT_DOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5723 case VT_LDOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5731 if (dbt
== VT_INT
&& (type
->t
& (VT_BTYPE
| VT_UNSIGNED
)) != dbt
) {
5732 /* additional cast for char/short/bool... */
5736 } else if ((dbt
& VT_BTYPE
) == VT_LLONG
) {
5737 if ((sbt
& VT_BTYPE
) != VT_LLONG
) {
5738 /* scalar to long long */
5740 if (sbt
== (VT_INT
| VT_UNSIGNED
))
5741 vtop
->c
.ll
= vtop
->c
.ui
;
5743 vtop
->c
.ll
= vtop
->c
.i
;
5745 /* machine independent conversion */
5747 /* generate high word */
5748 if (sbt
== (VT_INT
| VT_UNSIGNED
)) {
5756 /* patch second register */
5757 vtop
[-1].r2
= vtop
->r
;
5761 } else if (dbt
== VT_BOOL
) {
5762 /* scalar to bool */
5765 } else if ((dbt
& VT_BTYPE
) == VT_BYTE
||
5766 (dbt
& VT_BTYPE
) == VT_SHORT
) {
5767 force_charshort_cast(dbt
);
5768 } else if ((dbt
& VT_BTYPE
) == VT_INT
) {
5770 if (sbt
== VT_LLONG
) {
5771 /* from long long: just take low order word */
5775 /* if lvalue and single word type, nothing to do because
5776 the lvalue already contains the real type size (see
5777 VT_LVAL_xxx constants) */
5783 /* return type size. Put alignment at 'a' */
5784 static int type_size(CType
*type
, int *a
)
5789 bt
= type
->t
& VT_BTYPE
;
5790 if (bt
== VT_STRUCT
) {
5795 } else if (bt
== VT_PTR
) {
5796 if (type
->t
& VT_ARRAY
) {
5798 return type_size(&s
->type
, a
) * s
->c
;
5803 } else if (bt
== VT_LDOUBLE
) {
5805 return LDOUBLE_SIZE
;
5806 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
5807 #ifdef TCC_TARGET_I386
5813 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
5816 } else if (bt
== VT_SHORT
) {
5820 /* char, void, function, _Bool */
5826 /* return the pointed type of t */
5827 static inline CType
*pointed_type(CType
*type
)
5829 return &type
->ref
->type
;
5832 /* modify type so that its it is a pointer to type. */
5833 static void mk_pointer(CType
*type
)
5836 s
= sym_push(SYM_FIELD
, type
, 0, -1);
5837 type
->t
= VT_PTR
| (type
->t
& ~VT_TYPE
);
5841 /* compare function types. OLD functions match any new functions */
5842 static int is_compatible_func(CType
*type1
, CType
*type2
)
5848 if (!is_compatible_types(&s1
->type
, &s2
->type
))
5850 /* check func_call */
5853 /* XXX: not complete */
5854 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
5858 while (s1
!= NULL
) {
5861 if (!is_compatible_types(&s1
->type
, &s2
->type
))
5871 /* return true if type1 and type2 are exactly the same (including
5874 - enums are not checked as gcc __builtin_types_compatible_p ()
5876 static int is_compatible_types(CType
*type1
, CType
*type2
)
5880 t1
= type1
->t
& VT_TYPE
;
5881 t2
= type2
->t
& VT_TYPE
;
5882 /* XXX: bitfields ? */
5885 /* test more complicated cases */
5886 bt1
= t1
& VT_BTYPE
;
5887 if (bt1
== VT_PTR
) {
5888 type1
= pointed_type(type1
);
5889 type2
= pointed_type(type2
);
5890 return is_compatible_types(type1
, type2
);
5891 } else if (bt1
== VT_STRUCT
) {
5892 return (type1
->ref
== type2
->ref
);
5893 } else if (bt1
== VT_FUNC
) {
5894 return is_compatible_func(type1
, type2
);
5900 /* print a type. If 'varstr' is not NULL, then the variable is also
5901 printed in the type */
5903 /* XXX: add array and function pointers */
5904 void type_to_str(char *buf
, int buf_size
,
5905 CType
*type
, const char *varstr
)
5912 t
= type
->t
& VT_TYPE
;
5915 if (t
& VT_CONSTANT
)
5916 pstrcat(buf
, buf_size
, "const ");
5917 if (t
& VT_VOLATILE
)
5918 pstrcat(buf
, buf_size
, "volatile ");
5919 if (t
& VT_UNSIGNED
)
5920 pstrcat(buf
, buf_size
, "unsigned ");
5950 tstr
= "long double";
5952 pstrcat(buf
, buf_size
, tstr
);
5956 if (bt
== VT_STRUCT
)
5960 pstrcat(buf
, buf_size
, tstr
);
5961 v
= type
->ref
->v
& ~SYM_STRUCT
;
5962 if (v
>= SYM_FIRST_ANOM
)
5963 pstrcat(buf
, buf_size
, "<anonymous>");
5965 pstrcat(buf
, buf_size
, get_tok_str(v
, NULL
));
5969 type_to_str(buf
, buf_size
, &s
->type
, varstr
);
5970 pstrcat(buf
, buf_size
, "(");
5972 while (sa
!= NULL
) {
5973 type_to_str(buf1
, sizeof(buf1
), &sa
->type
, NULL
);
5974 pstrcat(buf
, buf_size
, buf1
);
5977 pstrcat(buf
, buf_size
, ", ");
5979 pstrcat(buf
, buf_size
, ")");
5983 pstrcpy(buf1
, sizeof(buf1
), "*");
5985 pstrcat(buf1
, sizeof(buf1
), varstr
);
5986 type_to_str(buf
, buf_size
, &s
->type
, buf1
);
5990 pstrcat(buf
, buf_size
, " ");
5991 pstrcat(buf
, buf_size
, varstr
);
5996 /* verify type compatibility to store vtop in 'dt' type, and generate
5998 static void gen_assign_cast(CType
*dt
)
6000 CType
*st
, *type1
, *type2
, tmp_type1
, tmp_type2
;
6001 char buf1
[256], buf2
[256];
6004 st
= &vtop
->type
; /* source type */
6005 dbt
= dt
->t
& VT_BTYPE
;
6006 sbt
= st
->t
& VT_BTYPE
;
6007 if (dt
->t
& VT_CONSTANT
)
6008 warning("assignment of read-only location");
6011 /* special cases for pointers */
6012 /* '0' can also be a pointer */
6013 if (is_null_pointer(vtop
))
6015 /* accept implicit pointer to integer cast with warning */
6016 if (is_integer_btype(sbt
)) {
6017 warning("assignment makes pointer from integer without a cast");
6020 type1
= pointed_type(dt
);
6021 /* a function is implicitely a function pointer */
6022 if (sbt
== VT_FUNC
) {
6023 if ((type1
->t
& VT_BTYPE
) != VT_VOID
&&
6024 !is_compatible_types(pointed_type(dt
), st
))
6031 type2
= pointed_type(st
);
6032 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
6033 (type2
->t
& VT_BTYPE
) == VT_VOID
) {
6034 /* void * can match anything */
6036 /* exact type match, except for unsigned */
6039 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6040 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6041 if (!is_compatible_types(&tmp_type1
, &tmp_type2
))
6044 /* check const and volatile */
6045 if ((!(type1
->t
& VT_CONSTANT
) && (type2
->t
& VT_CONSTANT
)) ||
6046 (!(type1
->t
& VT_VOLATILE
) && (type2
->t
& VT_VOLATILE
)))
6047 warning("assignment discards qualifiers from pointer target type");
6053 if (sbt
== VT_PTR
|| sbt
== VT_FUNC
) {
6054 warning("assignment makes integer from pointer without a cast");
6056 /* XXX: more tests */
6061 tmp_type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6062 tmp_type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6063 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
6065 type_to_str(buf1
, sizeof(buf1
), st
, NULL
);
6066 type_to_str(buf2
, sizeof(buf2
), dt
, NULL
);
6067 error("cannot cast '%s' to '%s'", buf1
, buf2
);
6075 /* store vtop in lvalue pushed on stack */
6078 int sbt
, dbt
, ft
, r
, t
, size
, align
, bit_size
, bit_pos
, rc
, delayed_cast
;
6080 ft
= vtop
[-1].type
.t
;
6081 sbt
= vtop
->type
.t
& VT_BTYPE
;
6082 dbt
= ft
& VT_BTYPE
;
6083 if (((sbt
== VT_INT
|| sbt
== VT_SHORT
) && dbt
== VT_BYTE
) ||
6084 (sbt
== VT_INT
&& dbt
== VT_SHORT
)) {
6085 /* optimize char/short casts */
6086 delayed_cast
= VT_MUSTCAST
;
6087 vtop
->type
.t
= ft
& VT_TYPE
;
6088 /* XXX: factorize */
6089 if (ft
& VT_CONSTANT
)
6090 warning("assignment of read-only location");
6093 if (!(ft
& VT_BITFIELD
))
6094 gen_assign_cast(&vtop
[-1].type
);
6097 if (sbt
== VT_STRUCT
) {
6098 /* if structure, only generate pointer */
6099 /* structure assignment : generate memcpy */
6100 /* XXX: optimize if small size */
6101 if (!nocode_wanted
) {
6102 size
= type_size(&vtop
->type
, &align
);
6104 vpush_global_sym(&func_old_type
, TOK_memcpy
);
6108 vtop
->type
.t
= VT_INT
;
6112 vtop
->type
.t
= VT_INT
;
6124 /* leave source on stack */
6125 } else if (ft
& VT_BITFIELD
) {
6126 /* bitfield store handling */
6127 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
6128 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
6129 /* remove bit field info to avoid loops */
6130 vtop
[-1].type
.t
= ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
6132 /* duplicate destination */
6134 vtop
[-1] = vtop
[-2];
6136 /* mask and shift source */
6137 vpushi((1 << bit_size
) - 1);
6141 /* load destination, mask and or with source */
6143 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
6149 #ifdef CONFIG_TCC_BCHECK
6150 /* bound check case */
6151 if (vtop
[-1].r
& VT_MUSTBOUND
) {
6157 if (!nocode_wanted
) {
6161 r
= gv(rc
); /* generate value */
6162 /* if lvalue was saved on stack, must read it */
6163 if ((vtop
[-1].r
& VT_VALMASK
) == VT_LLOCAL
) {
6165 t
= get_reg(RC_INT
);
6167 sv
.r
= VT_LOCAL
| VT_LVAL
;
6168 sv
.c
.ul
= vtop
[-1].c
.ul
;
6170 vtop
[-1].r
= t
| VT_LVAL
;
6173 /* two word case handling : store second register at word + 4 */
6174 if ((ft
& VT_BTYPE
) == VT_LLONG
) {
6176 /* convert to int to increment easily */
6177 vtop
->type
.t
= VT_INT
;
6183 /* XXX: it works because r2 is spilled last ! */
6184 store(vtop
->r2
, vtop
- 1);
6188 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
6189 vtop
->r
|= delayed_cast
;
6193 /* post defines POST/PRE add. c is the token ++ or -- */
6194 void inc(int post
, int c
)
6197 vdup(); /* save lvalue */
6199 gv_dup(); /* duplicate value */
6204 vpushi(c
- TOK_MID
);
6206 vstore(); /* store value */
6208 vpop(); /* if post op, return saved value */
6211 /* Parse GNUC __attribute__ extension. Currently, the following
6212 extensions are recognized:
6213 - aligned(n) : set data/function alignment.
6214 - packed : force data alignment to 1
6215 - section(x) : generate data/code in this section.
6216 - unused : currently ignored, but may be used someday.
6217 - regparm(n) : pass function parameters in registers (i386 only)
6219 static void parse_attribute(AttributeDef
*ad
)
6223 while (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
) {
6227 while (tok
!= ')') {
6228 if (tok
< TOK_IDENT
)
6229 expect("attribute name");
6237 expect("section name");
6238 ad
->section
= find_section(tcc_state
, (char *)tokc
.cstr
->data
);
6247 if (n
<= 0 || (n
& (n
- 1)) != 0)
6248 error("alignment must be a positive power of two");
6261 /* currently, no need to handle it because tcc does not
6262 track unused objects */
6266 /* currently, no need to handle it because tcc does not
6267 track unused objects */
6272 ad
->func_call
= FUNC_CDECL
;
6277 ad
->func_call
= FUNC_STDCALL
;
6279 #ifdef TCC_TARGET_I386
6289 ad
->func_call
= FUNC_FASTCALL1
+ n
- 1;
6294 if (tcc_state
->warn_unsupported
)
6295 warning("'%s' attribute ignored", get_tok_str(t
, NULL
));
6296 /* skip parameters */
6297 /* XXX: skip parenthesis too */
6300 while (tok
!= ')' && tok
!= -1)
6315 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6316 static void struct_decl(CType
*type
, int u
)
6318 int a
, v
, size
, align
, maxalign
, c
, offset
;
6319 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
;
6324 a
= tok
; /* save decl type */
6329 /* struct already defined ? return it */
6331 expect("struct/union/enum name");
6335 error("invalid type");
6342 /* we put an undefined size for struct/union */
6343 s
= sym_push(v
| SYM_STRUCT
, &type1
, 0, -1);
6344 s
->r
= 0; /* default alignment is zero as gcc */
6345 /* put struct/union/enum name in type */
6353 error("struct/union/enum already defined");
6354 /* cannot be empty */
6356 /* non empty enums are not allowed */
6357 if (a
== TOK_ENUM
) {
6361 expect("identifier");
6367 /* enum symbols have static storage */
6368 ss
= sym_push(v
, &int_type
, VT_CONST
, c
);
6369 ss
->type
.t
|= VT_STATIC
;
6374 /* NOTE: we accept a trailing comma */
6384 while (tok
!= '}') {
6385 parse_btype(&btype
, &ad
);
6391 type_decl(&type1
, &ad
, &v
, TYPE_DIRECT
);
6392 if ((type1
.t
& VT_BTYPE
) == VT_FUNC
||
6393 (type1
.t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
| VT_INLINE
)))
6394 error("invalid type for '%s'",
6395 get_tok_str(v
, NULL
));
6399 bit_size
= expr_const();
6400 /* XXX: handle v = 0 case for messages */
6402 error("negative width in bit-field '%s'",
6403 get_tok_str(v
, NULL
));
6404 if (v
&& bit_size
== 0)
6405 error("zero width for bit-field '%s'",
6406 get_tok_str(v
, NULL
));
6408 size
= type_size(&type1
, &align
);
6410 if (align
< ad
.aligned
)
6412 } else if (ad
.packed
) {
6416 if (bit_size
>= 0) {
6417 bt
= type1
.t
& VT_BTYPE
;
6423 error("bitfields must have scalar type");
6425 if (bit_size
> bsize
) {
6426 error("width of '%s' exceeds its type",
6427 get_tok_str(v
, NULL
));
6428 } else if (bit_size
== bsize
) {
6429 /* no need for bit fields */
6431 } else if (bit_size
== 0) {
6432 /* XXX: what to do if only padding in a
6434 /* zero size: means to pad */
6438 /* we do not have enough room ? */
6439 if ((bit_pos
+ bit_size
) > bsize
)
6442 /* XXX: handle LSB first */
6443 type1
.t
|= VT_BITFIELD
|
6444 (bit_pos
<< VT_STRUCT_SHIFT
) |
6445 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
6446 bit_pos
+= bit_size
;
6452 /* add new memory data only if starting
6454 if (lbit_pos
== 0) {
6455 if (a
== TOK_STRUCT
) {
6456 c
= (c
+ align
- 1) & -align
;
6464 if (align
> maxalign
)
6468 printf("add field %s offset=%d",
6469 get_tok_str(v
, NULL
), offset
);
6470 if (type1
.t
& VT_BITFIELD
) {
6471 printf(" pos=%d size=%d",
6472 (type1
.t
>> VT_STRUCT_SHIFT
) & 0x3f,
6473 (type1
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
6477 ss
= sym_push(v
| SYM_FIELD
, &type1
, 0, offset
);
6481 if (tok
== ';' || tok
== TOK_EOF
)
6488 /* store size and alignment */
6489 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
6495 /* return 0 if no type declaration. otherwise, return the basic type
6498 static int parse_btype(CType
*type
, AttributeDef
*ad
)
6500 int t
, u
, type_found
, typespec_found
;
6504 memset(ad
, 0, sizeof(AttributeDef
));
6511 /* currently, we really ignore extension */
6521 if ((t
& VT_BTYPE
) != 0)
6522 error("too many basic types");
6538 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
6539 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6540 } else if ((t
& VT_BTYPE
) == VT_LONG
) {
6541 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
6555 if ((t
& VT_BTYPE
) == VT_LONG
) {
6556 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6563 struct_decl(&type1
, VT_ENUM
);
6566 type
->ref
= type1
.ref
;
6570 struct_decl(&type1
, VT_STRUCT
);
6573 /* type modifiers */
6626 /* GNUC attribute */
6627 case TOK_ATTRIBUTE1
:
6628 case TOK_ATTRIBUTE2
:
6629 parse_attribute(ad
);
6636 parse_expr_type(&type1
);
6642 if (!s
|| !(s
->type
.t
& VT_TYPEDEF
))
6644 t
|= (s
->type
.t
& ~VT_TYPEDEF
);
6645 type
->ref
= s
->type
.ref
;
6652 if ((t
& (VT_SIGNED
|VT_UNSIGNED
)) == (VT_SIGNED
|VT_UNSIGNED
))
6653 error("signed and unsigned modifier");
6654 if (tcc_state
->char_is_unsigned
) {
6655 if ((t
& (VT_SIGNED
|VT_UNSIGNED
|VT_BTYPE
)) == VT_BYTE
)
6660 /* long is never used as type */
6661 if ((t
& VT_BTYPE
) == VT_LONG
)
6662 t
= (t
& ~VT_BTYPE
) | VT_INT
;
6667 /* convert a function parameter type (array to pointer and function to
6668 function pointer) */
6669 static inline void convert_parameter_type(CType
*pt
)
6671 /* remove const and volatile qualifiers (XXX: const could be used
6672 to indicate a const function parameter */
6673 pt
->t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6674 /* array must be transformed to pointer according to ANSI C */
6676 if ((pt
->t
& VT_BTYPE
) == VT_FUNC
) {
6681 static void post_type(CType
*type
, AttributeDef
*ad
)
6684 Sym
**plast
, *s
, *first
;
6689 /* function declaration */
6694 while (tok
!= ')') {
6695 /* read param name and compute offset */
6696 if (l
!= FUNC_OLD
) {
6697 if (!parse_btype(&pt
, &ad1
)) {
6699 error("invalid type");
6706 if ((pt
.t
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
6708 type_decl(&pt
, &ad1
, &n
, TYPE_DIRECT
| TYPE_ABSTRACT
);
6709 if ((pt
.t
& VT_BTYPE
) == VT_VOID
)
6710 error("parameter declared as void");
6717 convert_parameter_type(&pt
);
6718 s
= sym_push(n
| SYM_FIELD
, &pt
, 0, 0);
6723 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
6730 /* if no parameters, then old type prototype */
6734 t1
= type
->t
& VT_STORAGE
;
6735 /* NOTE: const is ignored in returned type as it has a special
6736 meaning in gcc / C++ */
6737 type
->t
&= ~(VT_STORAGE
| VT_CONSTANT
);
6738 post_type(type
, ad
);
6739 /* we push a anonymous symbol which will contain the function prototype */
6740 s
= sym_push(SYM_FIELD
, type
, ad
->func_call
, l
);
6742 type
->t
= t1
| VT_FUNC
;
6744 } else if (tok
== '[') {
6745 /* array definition */
6751 error("invalid array size");
6754 /* parse next post type */
6755 t1
= type
->t
& VT_STORAGE
;
6756 type
->t
&= ~VT_STORAGE
;
6757 post_type(type
, ad
);
6759 /* we push a anonymous symbol which will contain the array
6761 s
= sym_push(SYM_FIELD
, type
, 0, n
);
6762 type
->t
= t1
| VT_ARRAY
| VT_PTR
;
6767 /* Parse a type declaration (except basic type), and return the type
6768 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6769 expected. 'type' should contain the basic type. 'ad' is the
6770 attribute definition of the basic type. It can be modified by
6773 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
)
6776 CType type1
, *type2
;
6779 while (tok
== '*') {
6787 qualifiers
|= VT_CONSTANT
;
6792 qualifiers
|= VT_VOLATILE
;
6800 type
->t
|= qualifiers
;
6803 /* XXX: clarify attribute handling */
6804 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
6805 parse_attribute(ad
);
6807 /* recursive type */
6808 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6809 type1
.t
= 0; /* XXX: same as int */
6812 /* XXX: this is not correct to modify 'ad' at this point, but
6813 the syntax is not clear */
6814 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
6815 parse_attribute(ad
);
6816 type_decl(&type1
, ad
, v
, td
);
6819 /* type identifier */
6820 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
6824 if (!(td
& TYPE_ABSTRACT
))
6825 expect("identifier");
6829 post_type(type
, ad
);
6830 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
6831 parse_attribute(ad
);
6834 /* append type at the end of type1 */
6847 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
6848 static int lvalue_type(int t
)
6853 if (bt
== VT_BYTE
|| bt
== VT_BOOL
)
6855 else if (bt
== VT_SHORT
)
6859 if (t
& VT_UNSIGNED
)
6860 r
|= VT_LVAL_UNSIGNED
;
6864 /* indirection with full error checking and bound check */
6865 static void indir(void)
6867 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
6869 if ((vtop
->r
& VT_LVAL
) && !nocode_wanted
)
6871 vtop
->type
= *pointed_type(&vtop
->type
);
6872 /* an array is never an lvalue */
6873 if (!(vtop
->type
.t
& VT_ARRAY
)) {
6874 vtop
->r
|= lvalue_type(vtop
->type
.t
);
6875 /* if bound checking, the referenced pointer must be checked */
6876 if (do_bounds_check
)
6877 vtop
->r
|= VT_MUSTBOUND
;
6881 /* pass a parameter to a function and do type checking and casting */
6882 static void gfunc_param_typed(Sym
*func
, Sym
*arg
)
6887 func_type
= func
->c
;
6888 if (func_type
== FUNC_OLD
||
6889 (func_type
== FUNC_ELLIPSIS
&& arg
== NULL
)) {
6890 /* default casting : only need to convert float to double */
6891 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FLOAT
) {
6895 } else if (arg
== NULL
) {
6896 error("too many arguments to function");
6899 type
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
6900 gen_assign_cast(&type
);
6904 /* parse an expression of the form '(type)' or '(expr)' and return its
6906 static void parse_expr_type(CType
*type
)
6912 if (parse_btype(type
, &ad
)) {
6913 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
6920 static void parse_type(CType
*type
)
6925 if (!parse_btype(type
, &ad
)) {
6928 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
6931 static void vpush_tokc(int t
)
6935 vsetc(&type
, VT_CONST
, &tokc
);
6938 static void unary(void)
6940 int n
, t
, align
, size
, r
;
6945 /* XXX: GCC 2.95.3 does not generate a table although it should be
6959 vpush_tokc(VT_INT
| VT_UNSIGNED
);
6963 vpush_tokc(VT_LLONG
);
6967 vpush_tokc(VT_LLONG
| VT_UNSIGNED
);
6971 vpush_tokc(VT_FLOAT
);
6975 vpush_tokc(VT_DOUBLE
);
6979 vpush_tokc(VT_LDOUBLE
);
6982 case TOK___FUNCTION__
:
6984 goto tok_identifier
;
6990 /* special function name identifier */
6991 len
= strlen(funcname
) + 1;
6992 /* generate char[len] type */
6997 vpush_ref(&type
, data_section
, data_section
->data_offset
, len
);
6998 ptr
= section_ptr_add(data_section
, len
);
6999 memcpy(ptr
, funcname
, len
);
7007 /* string parsing */
7010 if (tcc_state
->warn_write_strings
)
7015 memset(&ad
, 0, sizeof(AttributeDef
));
7016 decl_initializer_alloc(&type
, &ad
, VT_CONST
, 2, 0, 0);
7021 if (parse_btype(&type
, &ad
)) {
7022 type_decl(&type
, &ad
, &n
, TYPE_ABSTRACT
);
7024 /* check ISOC99 compound literal */
7026 /* data is allocated locally by default */
7031 /* all except arrays are lvalues */
7032 if (!(type
.t
& VT_ARRAY
))
7033 r
|= lvalue_type(type
.t
);
7034 memset(&ad
, 0, sizeof(AttributeDef
));
7035 decl_initializer_alloc(&type
, &ad
, r
, 1, 0, 0);
7040 } else if (tok
== '{') {
7041 /* save all registers */
7043 /* statement expression : we do not accept break/continue
7044 inside as GCC does */
7045 block(NULL
, NULL
, NULL
, NULL
, 0, 1);
7060 /* functions names must be treated as function pointers,
7061 except for unary '&' and sizeof. Since we consider that
7062 functions are not lvalues, we only have to handle it
7063 there and in function calls. */
7064 /* arrays can also be used although they are not lvalues */
7065 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
&&
7066 !(vtop
->type
.t
& VT_ARRAY
))
7068 mk_pointer(&vtop
->type
);
7074 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
)
7075 vtop
->c
.i
= !vtop
->c
.i
;
7076 else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
7077 vtop
->c
.i
= vtop
->c
.i
^ 1;
7079 vseti(VT_JMP
, gtst(1, 0));
7089 /* in order to force cast, we add zero */
7091 if ((vtop
->type
.t
& VT_BTYPE
) == VT_PTR
)
7092 error("pointer not accepted for unary plus");
7102 parse_expr_type(&type
);
7106 size
= type_size(&type
, &align
);
7107 if (t
== TOK_SIZEOF
) {
7109 error("sizeof applied to an incomplete type");
7116 case TOK_builtin_types_compatible_p
:
7125 type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7126 type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7127 vpushi(is_compatible_types(&type1
, &type2
));
7130 case TOK_builtin_constant_p
:
7132 int saved_nocode_wanted
, res
;
7135 saved_nocode_wanted
= nocode_wanted
;
7138 res
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
7140 nocode_wanted
= saved_nocode_wanted
;
7160 goto tok_identifier
;
7162 /* allow to take the address of a label */
7163 if (tok
< TOK_UIDENT
)
7164 expect("label identifier");
7165 s
= label_find(tok
);
7167 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
7169 if (s
->r
== LABEL_DECLARED
)
7170 s
->r
= LABEL_FORWARD
;
7173 s
->type
.t
= VT_VOID
;
7174 mk_pointer(&s
->type
);
7175 s
->type
.t
|= VT_STATIC
;
7177 vset(&s
->type
, VT_CONST
| VT_SYM
, 0);
7186 expect("identifier");
7190 error("'%s' undeclared", get_tok_str(t
, NULL
));
7191 /* for simple function calls, we tolerate undeclared
7192 external reference to int() function */
7193 if (tcc_state
->warn_implicit_function_declaration
)
7194 warning("implicit declaration of function '%s'",
7195 get_tok_str(t
, NULL
));
7196 s
= external_global_sym(t
, &func_old_type
, 0);
7198 if ((s
->type
.t
& (VT_STATIC
| VT_INLINE
| VT_BTYPE
)) ==
7199 (VT_STATIC
| VT_INLINE
| VT_FUNC
)) {
7200 /* if referencing an inline function, then we generate a
7201 symbol to it if not already done. It will have the
7202 effect to generate code for it at the end of the
7203 compilation unit. Inline function as always
7204 generated in the text section. */
7206 put_extern_sym(s
, text_section
, 0, 0);
7207 r
= VT_SYM
| VT_CONST
;
7211 vset(&s
->type
, r
, s
->c
);
7212 /* if forward reference, we must point to s */
7213 if (vtop
->r
& VT_SYM
) {
7220 /* post operations */
7222 if (tok
== TOK_INC
|| tok
== TOK_DEC
) {
7225 } else if (tok
== '.' || tok
== TOK_ARROW
) {
7227 if (tok
== TOK_ARROW
)
7232 /* expect pointer on structure */
7233 if ((vtop
->type
.t
& VT_BTYPE
) != VT_STRUCT
)
7234 expect("struct or union");
7238 while ((s
= s
->next
) != NULL
) {
7243 error("field not found");
7244 /* add field offset to pointer */
7245 vtop
->type
= char_pointer_type
; /* change type to 'char *' */
7248 /* change type to field type, and set to lvalue */
7249 vtop
->type
= s
->type
;
7250 /* an array is never an lvalue */
7251 if (!(vtop
->type
.t
& VT_ARRAY
)) {
7252 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7253 /* if bound checking, the referenced pointer must be checked */
7254 if (do_bounds_check
)
7255 vtop
->r
|= VT_MUSTBOUND
;
7258 } else if (tok
== '[') {
7264 } else if (tok
== '(') {
7270 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
) {
7271 /* pointer test (no array accepted) */
7272 if ((vtop
->type
.t
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
7273 vtop
->type
= *pointed_type(&vtop
->type
);
7274 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
)
7278 expect("function pointer");
7281 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
7283 /* get return type */
7286 sa
= s
->next
; /* first parameter */
7288 /* compute first implicit argument if a structure is returned */
7289 if ((s
->type
.t
& VT_BTYPE
) == VT_STRUCT
) {
7290 /* get some space for the returned structure */
7291 size
= type_size(&s
->type
, &align
);
7292 loc
= (loc
- size
) & -align
;
7294 ret
.r
= VT_LOCAL
| VT_LVAL
;
7295 /* pass it as 'int' to avoid structure arg passing
7297 vseti(VT_LOCAL
, loc
);
7303 /* return in register */
7304 if (is_float(ret
.type
.t
)) {
7307 if ((ret
.type
.t
& VT_BTYPE
) == VT_LLONG
)
7316 gfunc_param_typed(s
, sa
);
7326 error("too few arguments to function");
7328 if (!nocode_wanted
) {
7329 gfunc_call(nb_args
);
7331 vtop
-= (nb_args
+ 1);
7334 vsetc(&ret
.type
, ret
.r
, &ret
.c
);
7342 static void uneq(void)
7348 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
7349 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
7350 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
7365 static void expr_prod(void)
7370 while (tok
== '*' || tok
== '/' || tok
== '%') {
7378 static void expr_sum(void)
7383 while (tok
== '+' || tok
== '-') {
7391 static void expr_shift(void)
7396 while (tok
== TOK_SHL
|| tok
== TOK_SAR
) {
7404 static void expr_cmp(void)
7409 while ((tok
>= TOK_ULE
&& tok
<= TOK_GT
) ||
7410 tok
== TOK_ULT
|| tok
== TOK_UGE
) {
7418 static void expr_cmpeq(void)
7423 while (tok
== TOK_EQ
|| tok
== TOK_NE
) {
7431 static void expr_and(void)
7434 while (tok
== '&') {
7441 static void expr_xor(void)
7444 while (tok
== '^') {
7451 static void expr_or(void)
7454 while (tok
== '|') {
7461 /* XXX: fix this mess */
7462 static void expr_land_const(void)
7465 while (tok
== TOK_LAND
) {
7472 /* XXX: fix this mess */
7473 static void expr_lor_const(void)
7476 while (tok
== TOK_LOR
) {
7483 /* only used if non constant */
7484 static void expr_land(void)
7489 if (tok
== TOK_LAND
) {
7493 if (tok
!= TOK_LAND
) {
7503 static void expr_lor(void)
7508 if (tok
== TOK_LOR
) {
7512 if (tok
!= TOK_LOR
) {
7522 /* XXX: better constant handling */
7523 static void expr_eq(void)
7525 int tt
, u
, r1
, r2
, rc
, t1
, t2
, bt1
, bt2
;
7527 CType type
, type1
, type2
;
7536 if (tok
== ':' && gnu_ext
) {
7552 if (vtop
!= vstack
) {
7553 /* needed to avoid having different registers saved in
7555 if (is_float(vtop
->type
.t
))
7562 if (tok
== ':' && gnu_ext
) {
7570 sv
= *vtop
; /* save value to handle it later */
7571 vtop
--; /* no vpop so that FP stack is not flushed */
7579 bt1
= t1
& VT_BTYPE
;
7581 bt2
= t2
& VT_BTYPE
;
7582 /* cast operands to correct type according to ISOC rules */
7583 if (is_float(bt1
) || is_float(bt2
)) {
7584 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
7585 type
.t
= VT_LDOUBLE
;
7586 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
7591 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
7592 /* cast to biggest op */
7594 /* convert to unsigned if it does not fit in a long long */
7595 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
7596 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
7597 type
.t
|= VT_UNSIGNED
;
7598 } else if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
7599 /* XXX: test pointer compatibility */
7601 } else if (bt1
== VT_STRUCT
|| bt2
== VT_STRUCT
) {
7602 /* XXX: test structure compatibility */
7604 } else if (bt1
== VT_VOID
|| bt2
== VT_VOID
) {
7605 /* NOTE: as an extension, we accept void on only one side */
7608 /* integer operations */
7610 /* convert to unsigned if it does not fit in an integer */
7611 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
7612 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
7613 type
.t
|= VT_UNSIGNED
;
7616 /* now we convert second operand */
7619 if (is_float(type
.t
)) {
7621 } else if ((type
.t
& VT_BTYPE
) == VT_LLONG
) {
7622 /* for long longs, we use fixed registers to avoid having
7623 to handle a complicated move */
7628 /* this is horrible, but we must also convert first
7632 /* put again first value and cast it */
7643 static void gexpr(void)
7654 /* parse an expression and return its type without any side effect. */
7655 static void expr_type(CType
*type
)
7657 int saved_nocode_wanted
;
7659 saved_nocode_wanted
= nocode_wanted
;
7664 nocode_wanted
= saved_nocode_wanted
;
7667 /* parse a unary expression and return its type without any side
7669 static void unary_type(CType
*type
)
7681 /* parse a constant expression and return value in vtop. */
7682 static void expr_const1(void)
7691 /* parse an integer constant and return its value. */
7692 static int expr_const(void)
7696 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
7697 expect("constant expression");
7703 /* return the label token if current token is a label, otherwise
7705 static int is_label(void)
7709 /* fast test first */
7710 if (tok
< TOK_UIDENT
)
7712 /* no need to save tokc because tok is an identifier */
7719 unget_tok(last_tok
);
7724 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
7725 int case_reg
, int is_expr
)
7730 /* generate line number info */
7732 (last_line_num
!= file
->line_num
|| last_ind
!= ind
)) {
7733 put_stabn(N_SLINE
, 0, file
->line_num
, ind
- func_ind
);
7735 last_line_num
= file
->line_num
;
7739 /* default return value is (void) */
7741 vtop
->type
.t
= VT_VOID
;
7744 if (tok
== TOK_IF
) {
7751 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
7753 if (c
== TOK_ELSE
) {
7757 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
7758 gsym(d
); /* patch else jmp */
7761 } else if (tok
== TOK_WHILE
) {
7769 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
7773 } else if (tok
== '{') {
7777 /* record local declaration stack position */
7779 llabel
= local_label_stack
;
7780 /* handle local labels declarations */
7781 if (tok
== TOK_LABEL
) {
7784 if (tok
< TOK_UIDENT
)
7785 expect("label identifier");
7786 label_push(&local_label_stack
, tok
, LABEL_DECLARED
);
7796 while (tok
!= '}') {
7801 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
7804 /* pop locally defined labels */
7805 label_pop(&local_label_stack
, llabel
);
7806 /* pop locally defined symbols */
7807 sym_pop(&local_stack
, s
);
7809 } else if (tok
== TOK_RETURN
) {
7813 gen_assign_cast(&func_vt
);
7814 if ((func_vt
.t
& VT_BTYPE
) == VT_STRUCT
) {
7816 /* if returning structure, must copy it to implicit
7817 first pointer arg location */
7820 vset(&type
, VT_LOCAL
| VT_LVAL
, func_vc
);
7823 /* copy structure value to pointer */
7825 } else if (is_float(func_vt
.t
)) {
7830 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
7833 rsym
= gjmp(rsym
); /* jmp */
7834 } else if (tok
== TOK_BREAK
) {
7837 error("cannot break");
7838 *bsym
= gjmp(*bsym
);
7841 } else if (tok
== TOK_CONTINUE
) {
7844 error("cannot continue");
7845 *csym
= gjmp(*csym
);
7848 } else if (tok
== TOK_FOR
) {
7875 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
7880 if (tok
== TOK_DO
) {
7885 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
7896 if (tok
== TOK_SWITCH
) {
7900 /* XXX: other types than integer */
7901 case_reg
= gv(RC_INT
);
7905 b
= gjmp(0); /* jump to first case */
7907 block(&a
, csym
, &b
, &c
, case_reg
, 0);
7908 /* if no default, jmp after switch */
7916 if (tok
== TOK_CASE
) {
7923 if (gnu_ext
&& tok
== TOK_DOTS
) {
7927 warning("empty case range");
7929 /* since a case is like a label, we must skip it with a jmp */
7936 *case_sym
= gtst(1, 0);
7939 *case_sym
= gtst(1, 0);
7943 *case_sym
= gtst(1, *case_sym
);
7948 goto block_after_label
;
7950 if (tok
== TOK_DEFAULT
) {
7956 error("too many 'default'");
7959 goto block_after_label
;
7961 if (tok
== TOK_GOTO
) {
7963 if (tok
== '*' && gnu_ext
) {
7967 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
7970 } else if (tok
>= TOK_UIDENT
) {
7971 s
= label_find(tok
);
7972 /* put forward definition if needed */
7974 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
7976 if (s
->r
== LABEL_DECLARED
)
7977 s
->r
= LABEL_FORWARD
;
7979 /* label already defined */
7980 if (s
->r
& LABEL_FORWARD
)
7981 s
->next
= (void *)gjmp((long)s
->next
);
7983 gjmp_addr((long)s
->next
);
7986 expect("label identifier");
7989 } else if (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
) {
7997 if (s
->r
== LABEL_DEFINED
)
7998 error("duplicate label '%s'", get_tok_str(s
->v
, NULL
));
7999 gsym((long)s
->next
);
8000 s
->r
= LABEL_DEFINED
;
8002 s
= label_push(&global_label_stack
, b
, LABEL_DEFINED
);
8004 s
->next
= (void *)ind
;
8005 /* we accept this, but it is a mistake */
8008 warning("deprecated use of label at end of compound statement");
8012 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
8015 /* expression case */
8030 /* t is the array or struct type. c is the array or struct
8031 address. cur_index/cur_field is the pointer to the current
8032 value. 'size_only' is true if only size info is needed (only used
8034 static void decl_designator(CType
*type
, Section
*sec
, unsigned long c
,
8035 int *cur_index
, Sym
**cur_field
,
8039 int notfirst
, index
, index_last
, align
, l
, nb_elems
, elem_size
;
8045 if (gnu_ext
&& (l
= is_label()) != 0)
8047 while (tok
== '[' || tok
== '.') {
8049 if (!(type
->t
& VT_ARRAY
))
8050 expect("array type");
8053 index
= expr_const();
8054 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
8055 expect("invalid index");
8056 if (tok
== TOK_DOTS
&& gnu_ext
) {
8058 index_last
= expr_const();
8059 if (index_last
< 0 ||
8060 (s
->c
>= 0 && index_last
>= s
->c
) ||
8062 expect("invalid index");
8068 *cur_index
= index_last
;
8069 type
= pointed_type(type
);
8070 elem_size
= type_size(type
, &align
);
8071 c
+= index
* elem_size
;
8072 /* NOTE: we only support ranges for last designator */
8073 nb_elems
= index_last
- index
+ 1;
8074 if (nb_elems
!= 1) {
8083 if ((type
->t
& VT_BTYPE
) != VT_STRUCT
)
8084 expect("struct/union type");
8097 /* XXX: fix this mess by using explicit storage field */
8099 type1
.t
|= (type
->t
& ~VT_TYPE
);
8113 if (type
->t
& VT_ARRAY
) {
8115 type
= pointed_type(type
);
8116 c
+= index
* type_size(type
, &align
);
8120 error("too many field init");
8121 /* XXX: fix this mess by using explicit storage field */
8123 type1
.t
|= (type
->t
& ~VT_TYPE
);
8128 decl_initializer(type
, sec
, c
, 0, size_only
);
8130 /* XXX: make it more general */
8131 if (!size_only
&& nb_elems
> 1) {
8132 unsigned long c_end
;
8137 error("range init not supported yet for dynamic storage");
8138 c_end
= c
+ nb_elems
* elem_size
;
8139 if (c_end
> sec
->data_allocated
)
8140 section_realloc(sec
, c_end
);
8141 src
= sec
->data
+ c
;
8143 for(i
= 1; i
< nb_elems
; i
++) {
8145 memcpy(dst
, src
, elem_size
);
8151 #define EXPR_CONST 1
8154 /* store a value or an expression directly in global data or in local array */
8155 static void init_putv(CType
*type
, Section
*sec
, unsigned long c
,
8156 int v
, int expr_type
)
8158 int saved_global_expr
, bt
, bit_pos
, bit_size
;
8160 unsigned long long bit_mask
;
8168 /* compound literals must be allocated globally in this case */
8169 saved_global_expr
= global_expr
;
8172 global_expr
= saved_global_expr
;
8173 /* NOTE: symbols are accepted */
8174 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) != VT_CONST
)
8175 error("initializer element is not constant");
8183 dtype
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
8186 /* XXX: not portable */
8187 /* XXX: generate error if incorrect relocation */
8188 gen_assign_cast(&dtype
);
8189 bt
= type
->t
& VT_BTYPE
;
8190 ptr
= sec
->data
+ c
;
8191 /* XXX: make code faster ? */
8192 if (!(type
->t
& VT_BITFIELD
)) {
8197 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
8198 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
8199 bit_mask
= (1LL << bit_size
) - 1;
8201 if ((vtop
->r
& VT_SYM
) &&
8207 (bt
== VT_INT
&& bit_size
!= 32)))
8208 error("initializer element is not computable at load time");
8211 *(char *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8214 *(short *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8217 *(double *)ptr
= vtop
->c
.d
;
8220 *(long double *)ptr
= vtop
->c
.ld
;
8223 *(long long *)ptr
|= (vtop
->c
.ll
& bit_mask
) << bit_pos
;
8226 if (vtop
->r
& VT_SYM
) {
8227 greloc(sec
, vtop
->sym
, c
, R_DATA_32
);
8229 *(int *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8234 vset(&dtype
, VT_LOCAL
, c
);
8241 /* put zeros for variable based init */
8242 static void init_putz(CType
*t
, Section
*sec
, unsigned long c
, int size
)
8245 /* nothing to do because globals are already set to zero */
8247 vpush_global_sym(&func_old_type
, TOK_memset
);
8255 /* 't' contains the type and storage info. 'c' is the offset of the
8256 object in section 'sec'. If 'sec' is NULL, it means stack based
8257 allocation. 'first' is true if array '{' must be read (multi
8258 dimension implicit array init handling). 'size_only' is true if
8259 size only evaluation is wanted (only for arrays). */
8260 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
8261 int first
, int size_only
)
8263 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
8264 int size1
, align1
, expr_type
;
8268 if (type
->t
& VT_ARRAY
) {
8272 t1
= pointed_type(type
);
8273 size1
= type_size(t1
, &align1
);
8276 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
8282 /* only parse strings here if correct type (otherwise: handle
8283 them as ((w)char *) expressions */
8284 if ((tok
== TOK_LSTR
&&
8285 (t1
->t
& VT_BTYPE
) == VT_INT
) ||
8287 (t1
->t
& VT_BTYPE
) == VT_BYTE
)) {
8288 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8293 /* compute maximum number of chars wanted */
8295 cstr_len
= cstr
->size
;
8297 cstr_len
= cstr
->size
/ sizeof(int);
8300 if (n
>= 0 && nb
> (n
- array_length
))
8301 nb
= n
- array_length
;
8304 warning("initializer-string for array is too long");
8305 /* in order to go faster for common case (char
8306 string in global variable, we handle it
8308 if (sec
&& tok
== TOK_STR
&& size1
== 1) {
8309 memcpy(sec
->data
+ c
+ array_length
, cstr
->data
, nb
);
8313 ch
= ((unsigned char *)cstr
->data
)[i
];
8315 ch
= ((int *)cstr
->data
)[i
];
8316 init_putv(t1
, sec
, c
+ (array_length
+ i
) * size1
,
8324 /* only add trailing zero if enough storage (no
8325 warning in this case since it is standard) */
8326 if (n
< 0 || array_length
< n
) {
8328 init_putv(t1
, sec
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
8334 while (tok
!= '}') {
8335 decl_designator(type
, sec
, c
, &index
, NULL
, size_only
);
8336 if (n
>= 0 && index
>= n
)
8337 error("index too large");
8338 /* must put zero in holes (note that doing it that way
8339 ensures that it even works with designators) */
8340 if (!size_only
&& array_length
< index
) {
8341 init_putz(t1
, sec
, c
+ array_length
* size1
,
8342 (index
- array_length
) * size1
);
8345 if (index
> array_length
)
8346 array_length
= index
;
8347 /* special test for multi dimensional arrays (may not
8348 be strictly correct if designators are used at the
8350 if (index
>= n
&& no_oblock
)
8359 /* put zeros at the end */
8360 if (!size_only
&& n
>= 0 && array_length
< n
) {
8361 init_putz(t1
, sec
, c
+ array_length
* size1
,
8362 (n
- array_length
) * size1
);
8364 /* patch type size if needed */
8366 s
->c
= array_length
;
8367 } else if ((type
->t
& VT_BTYPE
) == VT_STRUCT
&&
8368 (sec
|| !first
|| tok
== '{')) {
8371 /* NOTE: the previous test is a specific case for automatic
8372 struct/union init */
8373 /* XXX: union needs only one init */
8375 /* XXX: this test is incorrect for local initializers
8376 beginning with ( without {. It would be much more difficult
8377 to do it correctly (ideally, the expression parser should
8378 be used in all cases) */
8384 while (tok
== '(') {
8388 if (!parse_btype(&type1
, &ad1
))
8390 type_decl(&type1
, &ad1
, &n
, TYPE_ABSTRACT
);
8392 if (!is_assignable_types(type
, &type1
))
8393 error("invalid type for cast");
8398 if (first
|| tok
== '{') {
8407 while (tok
!= '}') {
8408 decl_designator(type
, sec
, c
, NULL
, &f
, size_only
);
8410 if (!size_only
&& array_length
< index
) {
8411 init_putz(type
, sec
, c
+ array_length
,
8412 index
- array_length
);
8414 index
= index
+ type_size(&f
->type
, &align1
);
8415 if (index
> array_length
)
8416 array_length
= index
;
8418 if (no_oblock
&& f
== NULL
)
8424 /* put zeros at the end */
8425 if (!size_only
&& array_length
< n
) {
8426 init_putz(type
, sec
, c
+ array_length
,
8435 } else if (tok
== '{') {
8437 decl_initializer(type
, sec
, c
, first
, size_only
);
8439 } else if (size_only
) {
8440 /* just skip expression */
8442 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
8446 else if (tok
== ')')
8451 /* currently, we always use constant expression for globals
8452 (may change for scripting case) */
8453 expr_type
= EXPR_CONST
;
8455 expr_type
= EXPR_ANY
;
8456 init_putv(type
, sec
, c
, 0, expr_type
);
8460 /* parse an initializer for type 't' if 'has_init' is non zero, and
8461 allocate space in local or global data space ('r' is either
8462 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8463 variable 'v' of scope 'scope' is declared before initializers are
8464 parsed. If 'v' is zero, then a reference to the new object is put
8465 in the value stack. If 'has_init' is 2, a special parsing is done
8466 to handle string constants. */
8467 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
8468 int has_init
, int v
, int scope
)
8470 int size
, align
, addr
, data_offset
;
8472 ParseState saved_parse_state
;
8473 TokenString init_str
;
8476 size
= type_size(type
, &align
);
8477 /* If unknown size, we must evaluate it before
8478 evaluating initializers because
8479 initializers can generate global data too
8480 (e.g. string pointers or ISOC99 compound
8481 literals). It also simplifies local
8482 initializers handling */
8483 tok_str_new(&init_str
);
8486 error("unknown type size");
8487 /* get all init string */
8488 if (has_init
== 2) {
8489 /* only get strings */
8490 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8491 tok_str_add_tok(&init_str
);
8496 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
8498 error("unexpected end of file in initializer");
8499 tok_str_add_tok(&init_str
);
8502 else if (tok
== '}') {
8510 tok_str_add(&init_str
, -1);
8511 tok_str_add(&init_str
, 0);
8514 save_parse_state(&saved_parse_state
);
8516 macro_ptr
= init_str
.str
;
8518 decl_initializer(type
, NULL
, 0, 1, 1);
8519 /* prepare second initializer parsing */
8520 macro_ptr
= init_str
.str
;
8523 /* if still unknown size, error */
8524 size
= type_size(type
, &align
);
8526 error("unknown type size");
8528 /* take into account specified alignment if bigger */
8530 if (ad
->aligned
> align
)
8531 align
= ad
->aligned
;
8532 } else if (ad
->packed
) {
8535 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
8537 if (do_bounds_check
&& (type
->t
& VT_ARRAY
))
8539 loc
= (loc
- size
) & -align
;
8541 /* handles bounds */
8542 /* XXX: currently, since we do only one pass, we cannot track
8543 '&' operators, so we add only arrays */
8544 if (do_bounds_check
&& (type
->t
& VT_ARRAY
)) {
8545 unsigned long *bounds_ptr
;
8546 /* add padding between regions */
8548 /* then add local bound info */
8549 bounds_ptr
= section_ptr_add(lbounds_section
, 2 * sizeof(unsigned long));
8550 bounds_ptr
[0] = addr
;
8551 bounds_ptr
[1] = size
;
8554 /* local variable */
8555 sym_push(v
, type
, r
, addr
);
8557 /* push local reference */
8558 vset(type
, r
, addr
);
8564 if (v
&& scope
== VT_CONST
) {
8565 /* see if the symbol was already defined */
8568 if (!is_compatible_types(&sym
->type
, type
))
8569 error("incompatible types for redefinition of '%s'",
8570 get_tok_str(v
, NULL
));
8571 if (sym
->type
.t
& VT_EXTERN
) {
8572 /* if the variable is extern, it was not allocated */
8573 sym
->type
.t
&= ~VT_EXTERN
;
8574 /* set array size if it was ommited in extern
8576 if ((sym
->type
.t
& VT_ARRAY
) &&
8577 sym
->type
.ref
->c
< 0 &&
8579 sym
->type
.ref
->c
= type
->ref
->c
;
8581 /* we accept several definitions of the same
8582 global variable. this is tricky, because we
8583 must play with the SHN_COMMON type of the symbol */
8584 /* XXX: should check if the variable was already
8585 initialized. It is incorrect to initialized it
8587 /* no init data, we won't add more to the symbol */
8594 /* allocate symbol in corresponding section */
8599 else if (tcc_state
->nocommon
)
8603 data_offset
= sec
->data_offset
;
8604 data_offset
= (data_offset
+ align
- 1) & -align
;
8606 /* very important to increment global pointer at this time
8607 because initializers themselves can create new initializers */
8608 data_offset
+= size
;
8609 /* add padding if bound check */
8610 if (do_bounds_check
)
8612 sec
->data_offset
= data_offset
;
8613 /* allocate section space to put the data */
8614 if (sec
->sh_type
!= SHT_NOBITS
&&
8615 data_offset
> sec
->data_allocated
)
8616 section_realloc(sec
, data_offset
);
8617 /* align section if needed */
8618 if (align
> sec
->sh_addralign
)
8619 sec
->sh_addralign
= align
;
8621 addr
= 0; /* avoid warning */
8625 if (scope
== VT_CONST
) {
8630 sym
= sym_push(v
, type
, r
| VT_SYM
, 0);
8632 /* update symbol definition */
8634 put_extern_sym(sym
, sec
, addr
, size
);
8637 /* put a common area */
8638 put_extern_sym(sym
, NULL
, align
, size
);
8639 /* XXX: find a nicer way */
8640 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
8641 esym
->st_shndx
= SHN_COMMON
;
8646 /* push global reference */
8647 sym
= get_sym_ref(type
, sec
, addr
, size
);
8649 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
8653 /* handles bounds now because the symbol must be defined
8654 before for the relocation */
8655 if (do_bounds_check
) {
8656 unsigned long *bounds_ptr
;
8658 greloc(bounds_section
, sym
, bounds_section
->data_offset
, R_DATA_32
);
8659 /* then add global bound info */
8660 bounds_ptr
= section_ptr_add(bounds_section
, 2 * sizeof(long));
8661 bounds_ptr
[0] = 0; /* relocated */
8662 bounds_ptr
[1] = size
;
8666 decl_initializer(type
, sec
, addr
, 1, 0);
8667 /* restore parse state if needed */
8669 tok_str_free(init_str
.str
);
8670 restore_parse_state(&saved_parse_state
);
8676 void put_func_debug(Sym
*sym
)
8681 /* XXX: we put here a dummy type */
8682 snprintf(buf
, sizeof(buf
), "%s:%c1",
8683 funcname
, sym
->type
.t
& VT_STATIC
? 'f' : 'F');
8684 put_stabs_r(buf
, N_FUN
, 0, file
->line_num
, 0,
8685 cur_text_section
, sym
->c
);
8690 /* parse an old style function declaration list */
8691 /* XXX: check multiple parameter */
8692 static void func_decl_list(Sym
*func_sym
)
8699 /* parse each declaration */
8700 while (tok
!= '{' && tok
!= ';' && tok
!= ',' && tok
!= TOK_EOF
) {
8701 if (!parse_btype(&btype
, &ad
))
8702 expect("declaration list");
8703 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
8704 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
8706 /* we accept no variable after */
8710 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
8711 /* find parameter in function parameter list */
8714 if ((s
->v
& ~SYM_FIELD
) == v
)
8718 error("declaration for parameter '%s' but no such parameter",
8719 get_tok_str(v
, NULL
));
8721 /* check that no storage specifier except 'register' was given */
8722 if (type
.t
& VT_STORAGE
)
8723 error("storage class specified for '%s'", get_tok_str(v
, NULL
));
8724 convert_parameter_type(&type
);
8725 /* we can add the type (NOTE: it could be local to the function) */
8727 /* accept other parameters */
8738 /* parse a function defined by symbol 'sym' and generate its code in
8739 'cur_text_section' */
8740 static void gen_function(Sym
*sym
)
8742 ind
= cur_text_section
->data_offset
;
8743 /* NOTE: we patch the symbol size later */
8744 put_extern_sym(sym
, cur_text_section
, ind
, 0);
8745 funcname
= get_tok_str(sym
->v
, NULL
);
8747 /* put debug symbol */
8749 put_func_debug(sym
);
8750 /* push a dummy symbol to enable local sym storage */
8751 sym_push2(&local_stack
, SYM_FIELD
, 0, 0);
8752 gfunc_prolog(&sym
->type
);
8754 block(NULL
, NULL
, NULL
, NULL
, 0, 0);
8757 cur_text_section
->data_offset
= ind
;
8758 label_pop(&global_label_stack
, NULL
);
8759 sym_pop(&local_stack
, NULL
); /* reset local stack */
8760 /* end of function */
8761 /* patch symbol size */
8762 ((Elf32_Sym
*)symtab_section
->data
)[sym
->c
].st_size
=
8765 put_stabn(N_FUN
, 0, 0, ind
- func_ind
);
8767 funcname
= ""; /* for safety */
8768 func_vt
.t
= VT_VOID
; /* for safety */
8769 ind
= 0; /* for safety */
8772 static void gen_inline_functions(void)
8776 int *str
, inline_generated
;
8778 /* iterate while inline function are referenced */
8780 inline_generated
= 0;
8781 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
8783 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
8784 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
8785 (VT_STATIC
| VT_INLINE
) &&
8787 /* the function was used: generate its code and
8788 convert it to a normal function */
8789 str
= (int *)sym
->r
;
8790 sym
->r
= VT_SYM
| VT_CONST
;
8791 type
->t
&= ~VT_INLINE
;
8795 cur_text_section
= text_section
;
8797 macro_ptr
= NULL
; /* fail safe */
8800 inline_generated
= 1;
8803 if (!inline_generated
)
8807 /* free all remaining inline function tokens */
8808 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
8810 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
8811 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
8812 (VT_STATIC
| VT_INLINE
)) {
8813 str
= (int *)sym
->r
;
8815 sym
->r
= 0; /* fail safe */
8820 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8821 static void decl(int l
)
8829 if (!parse_btype(&btype
, &ad
)) {
8830 /* skip redundant ';' */
8831 /* XXX: find more elegant solution */
8836 if (l
== VT_CONST
&&
8837 (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
)) {
8838 /* global asm block */
8842 /* special test for old K&R protos without explicit int
8843 type. Only accepted when defining global data */
8844 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
8848 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
8849 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
8851 /* we accept no variable after */
8855 while (1) { /* iterate thru each declaration */
8857 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
8861 type_to_str(buf
, sizeof(buf
), t
, get_tok_str(v
, NULL
));
8862 printf("type = '%s'\n", buf
);
8865 if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
8866 /* if old style function prototype, we accept a
8869 if (sym
->c
== FUNC_OLD
)
8870 func_decl_list(sym
);
8875 error("cannot use local functions");
8876 if (!(type
.t
& VT_FUNC
))
8877 expect("function definition");
8879 /* reject abstract declarators in function definition */
8881 while ((sym
= sym
->next
) != NULL
)
8882 if (!(sym
->v
& ~SYM_FIELD
))
8883 expect("identifier");
8885 /* XXX: cannot do better now: convert extern line to static inline */
8886 if ((type
.t
& (VT_EXTERN
| VT_INLINE
)) == (VT_EXTERN
| VT_INLINE
))
8887 type
.t
= (type
.t
& ~VT_EXTERN
) | VT_STATIC
;
8891 if ((sym
->type
.t
& VT_BTYPE
) != VT_FUNC
)
8893 /* specific case: if not func_call defined, we put
8894 the one of the prototype */
8895 /* XXX: should have default value */
8896 if (sym
->type
.ref
->r
!= FUNC_CDECL
&&
8897 type
.ref
->r
== FUNC_CDECL
)
8898 type
.ref
->r
= sym
->type
.ref
->r
;
8899 if (!is_compatible_types(&sym
->type
, &type
)) {
8901 error("incompatible types for redefinition of '%s'",
8902 get_tok_str(v
, NULL
));
8904 /* if symbol is already defined, then put complete type */
8907 /* put function symbol */
8908 sym
= global_identifier_push(v
, type
.t
, 0);
8909 sym
->type
.ref
= type
.ref
;
8912 /* static inline functions are just recorded as a kind
8913 of macro. Their code will be emitted at the end of
8914 the compilation unit only if they are used */
8915 if ((type
.t
& (VT_INLINE
| VT_STATIC
)) ==
8916 (VT_INLINE
| VT_STATIC
)) {
8917 TokenString func_str
;
8920 tok_str_new(&func_str
);
8926 error("unexpected end of file");
8927 tok_str_add_tok(&func_str
);
8932 } else if (t
== '}') {
8934 if (block_level
== 0)
8938 tok_str_add(&func_str
, -1);
8939 tok_str_add(&func_str
, 0);
8940 sym
->r
= (int)func_str
.str
;
8942 /* compute text section */
8943 cur_text_section
= ad
.section
;
8944 if (!cur_text_section
)
8945 cur_text_section
= text_section
;
8946 sym
->r
= VT_SYM
| VT_CONST
;
8951 if (btype
.t
& VT_TYPEDEF
) {
8952 /* save typedefed type */
8953 /* XXX: test storage specifiers ? */
8954 sym
= sym_push(v
, &type
, 0, 0);
8955 sym
->type
.t
|= VT_TYPEDEF
;
8956 } else if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
8957 /* external function definition */
8958 /* specific case for func_call attribute */
8960 type
.ref
->r
= ad
.func_call
;
8961 external_sym(v
, &type
, 0);
8963 /* not lvalue if array */
8965 if (!(type
.t
& VT_ARRAY
))
8966 r
|= lvalue_type(type
.t
);
8967 has_init
= (tok
== '=');
8968 if ((btype
.t
& VT_EXTERN
) ||
8969 ((type
.t
& VT_ARRAY
) && (type
.t
& VT_STATIC
) &&
8970 !has_init
&& l
== VT_CONST
&& type
.ref
->c
< 0)) {
8971 /* external variable */
8972 /* NOTE: as GCC, uninitialized global static
8973 arrays of null size are considered as
8975 external_sym(v
, &type
, r
);
8977 if (type
.t
& VT_STATIC
)
8983 decl_initializer_alloc(&type
, &ad
, r
,
8997 /* better than nothing, but needs extension to handle '-E' option
8999 static void preprocess_init(TCCState
*s1
)
9001 s1
->include_stack_ptr
= s1
->include_stack
;
9002 /* XXX: move that before to avoid having to initialize
9003 file->ifdef_stack_ptr ? */
9004 s1
->ifdef_stack_ptr
= s1
->ifdef_stack
;
9005 file
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
9007 /* XXX: not ANSI compliant: bound checking says error */
9011 /* compile the C file opened in 'file'. Return non zero if errors. */
9012 static int tcc_compile(TCCState
*s1
)
9016 volatile int section_sym
;
9019 printf("%s: **** new file\n", file
->filename
);
9021 preprocess_init(s1
);
9024 anon_sym
= SYM_FIRST_ANOM
;
9026 /* file info: full path + filename */
9027 section_sym
= 0; /* avoid warning */
9029 section_sym
= put_elf_sym(symtab_section
, 0, 0,
9030 ELF32_ST_INFO(STB_LOCAL
, STT_SECTION
), 0,
9031 text_section
->sh_num
, NULL
);
9032 getcwd(buf
, sizeof(buf
));
9033 pstrcat(buf
, sizeof(buf
), "/");
9034 put_stabs_r(buf
, N_SO
, 0, 0,
9035 text_section
->data_offset
, text_section
, section_sym
);
9036 put_stabs_r(file
->filename
, N_SO
, 0, 0,
9037 text_section
->data_offset
, text_section
, section_sym
);
9039 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9040 symbols can be safely used */
9041 put_elf_sym(symtab_section
, 0, 0,
9042 ELF32_ST_INFO(STB_LOCAL
, STT_FILE
), 0,
9043 SHN_ABS
, file
->filename
);
9045 /* define some often used types */
9046 int_type
.t
= VT_INT
;
9048 char_pointer_type
.t
= VT_BYTE
;
9049 mk_pointer(&char_pointer_type
);
9051 func_old_type
.t
= VT_FUNC
;
9052 func_old_type
.ref
= sym_push(SYM_FIELD
, &int_type
, FUNC_CDECL
, FUNC_OLD
);
9055 /* define 'void *alloca(unsigned int)' builtin function */
9060 sym
= sym_push(p
, mk_pointer(VT_VOID
), FUNC_CDECL
, FUNC_NEW
);
9061 s1
= sym_push(SYM_FIELD
, VT_UNSIGNED
| VT_INT
, 0, 0);
9064 sym_push(TOK_alloca
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), VT_CONST
, 0);
9068 define_start
= define_stack
;
9070 if (setjmp(s1
->error_jmp_buf
) == 0) {
9072 s1
->error_set_jmp_enabled
= 1;
9074 ch
= file
->buf_ptr
[0];
9075 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
9076 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
;
9080 expect("declaration");
9082 /* end of translation unit info */
9084 put_stabs_r(NULL
, N_SO
, 0, 0,
9085 text_section
->data_offset
, text_section
, section_sym
);
9088 s1
->error_set_jmp_enabled
= 0;
9090 /* reset define stack, but leave -Dsymbols (may be incorrect if
9091 they are undefined) */
9092 free_defines(define_start
);
9094 gen_inline_functions();
9096 sym_pop(&global_stack
, NULL
);
9098 return s1
->nb_errors
!= 0 ? -1 : 0;
9102 int tcc_compile_string(TCCState
*s
, const char *str
)
9104 BufferedFile bf1
, *bf
= &bf1
;
9108 /* init file structure */
9110 /* XXX: avoid copying */
9112 buf
= tcc_malloc(len
+ 1);
9115 memcpy(buf
, str
, len
);
9118 bf
->buf_end
= buf
+ len
;
9119 pstrcpy(bf
->filename
, sizeof(bf
->filename
), "<string>");
9123 ret
= tcc_compile(s
);
9127 /* currently, no need to close */
9132 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9133 void tcc_define_symbol(TCCState
*s1
, const char *sym
, const char *value
)
9135 BufferedFile bf1
, *bf
= &bf1
;
9137 pstrcpy(bf
->buffer
, IO_BUF_SIZE
, sym
);
9138 pstrcat(bf
->buffer
, IO_BUF_SIZE
, " ");
9142 pstrcat(bf
->buffer
, IO_BUF_SIZE
, value
);
9144 /* init file structure */
9146 bf
->buf_ptr
= bf
->buffer
;
9147 bf
->buf_end
= bf
->buffer
+ strlen(bf
->buffer
);
9148 *bf
->buf_end
= CH_EOB
;
9149 bf
->filename
[0] = '\0';
9153 s1
->include_stack_ptr
= s1
->include_stack
;
9155 /* parse with define parser */
9156 ch
= file
->buf_ptr
[0];
9162 /* undefine a preprocessor symbol */
9163 void tcc_undefine_symbol(TCCState
*s1
, const char *sym
)
9167 ts
= tok_alloc(sym
, strlen(sym
));
9168 s
= define_find(ts
->tok
);
9169 /* undefine symbol by putting an invalid name */
9174 #ifdef CONFIG_TCC_ASM
9176 #ifdef TCC_TARGET_I386
9177 #include "i386-asm.c"
9182 static void asm_instr(void)
9184 error("inline asm() not supported");
9186 static void asm_global_instr(void)
9188 error("inline asm() not supported");
9194 #ifdef TCC_TARGET_COFF
9195 #include "tcccoff.c"
9198 /* print the position in the source file of PC value 'pc' by reading
9199 the stabs debug information */
9200 static void rt_printline(unsigned long wanted_pc
)
9202 Stab_Sym
*sym
, *sym_end
;
9203 char func_name
[128], last_func_name
[128];
9204 unsigned long func_addr
, last_pc
, pc
;
9205 const char *incl_files
[INCLUDE_STACK_SIZE
];
9206 int incl_index
, len
, last_line_num
, i
;
9207 const char *str
, *p
;
9209 fprintf(stderr
, "0x%08lx:", wanted_pc
);
9211 func_name
[0] = '\0';
9214 last_func_name
[0] = '\0';
9215 last_pc
= 0xffffffff;
9217 sym
= (Stab_Sym
*)stab_section
->data
+ 1;
9218 sym_end
= (Stab_Sym
*)(stab_section
->data
+ stab_section
->data_offset
);
9219 while (sym
< sym_end
) {
9220 switch(sym
->n_type
) {
9221 /* function start or end */
9223 if (sym
->n_strx
== 0) {
9224 /* we test if between last line and end of function */
9225 pc
= sym
->n_value
+ func_addr
;
9226 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
9228 func_name
[0] = '\0';
9231 str
= stabstr_section
->data
+ sym
->n_strx
;
9232 p
= strchr(str
, ':');
9234 pstrcpy(func_name
, sizeof(func_name
), str
);
9237 if (len
> sizeof(func_name
) - 1)
9238 len
= sizeof(func_name
) - 1;
9239 memcpy(func_name
, str
, len
);
9240 func_name
[len
] = '\0';
9242 func_addr
= sym
->n_value
;
9245 /* line number info */
9247 pc
= sym
->n_value
+ func_addr
;
9248 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
9251 last_line_num
= sym
->n_desc
;
9253 strcpy(last_func_name
, func_name
);
9257 str
= stabstr_section
->data
+ sym
->n_strx
;
9259 if (incl_index
< INCLUDE_STACK_SIZE
) {
9260 incl_files
[incl_index
++] = str
;
9268 if (sym
->n_strx
== 0) {
9269 incl_index
= 0; /* end of translation unit */
9271 str
= stabstr_section
->data
+ sym
->n_strx
;
9272 /* do not add path */
9274 if (len
> 0 && str
[len
- 1] != '/')
9282 /* second pass: we try symtab symbols (no line number info) */
9285 Elf32_Sym
*sym
, *sym_end
;
9288 sym_end
= (Elf32_Sym
*)(symtab_section
->data
+ symtab_section
->data_offset
);
9289 for(sym
= (Elf32_Sym
*)symtab_section
->data
+ 1;
9292 type
= ELF32_ST_TYPE(sym
->st_info
);
9293 if (type
== STT_FUNC
) {
9294 if (wanted_pc
>= sym
->st_value
&&
9295 wanted_pc
< sym
->st_value
+ sym
->st_size
) {
9296 pstrcpy(last_func_name
, sizeof(last_func_name
),
9297 strtab_section
->data
+ sym
->st_name
);
9303 /* did not find any info: */
9304 fprintf(stderr
, " ???\n");
9307 if (last_func_name
[0] != '\0') {
9308 fprintf(stderr
, " %s()", last_func_name
);
9310 if (incl_index
> 0) {
9311 fprintf(stderr
, " (%s:%d",
9312 incl_files
[incl_index
- 1], last_line_num
);
9313 for(i
= incl_index
- 2; i
>= 0; i
--)
9314 fprintf(stderr
, ", included from %s", incl_files
[i
]);
9315 fprintf(stderr
, ")");
9317 fprintf(stderr
, "\n");
9320 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
9324 /* fix for glibc 2.1 */
9330 /* return the PC at frame level 'level'. Return non zero if not found */
9331 static int rt_get_caller_pc(unsigned long *paddr
,
9332 ucontext_t
*uc
, int level
)
9338 #if defined(__FreeBSD__)
9339 *paddr
= uc
->uc_mcontext
.mc_eip
;
9340 #elif defined(__dietlibc__)
9341 *paddr
= uc
->uc_mcontext
.eip
;
9343 *paddr
= uc
->uc_mcontext
.gregs
[REG_EIP
];
9347 #if defined(__FreeBSD__)
9348 fp
= uc
->uc_mcontext
.mc_ebp
;
9349 #elif defined(__dietlibc__)
9350 fp
= uc
->uc_mcontext
.ebp
;
9352 fp
= uc
->uc_mcontext
.gregs
[REG_EBP
];
9354 for(i
=1;i
<level
;i
++) {
9355 /* XXX: check address validity with program info */
9356 if (fp
<= 0x1000 || fp
>= 0xc0000000)
9358 fp
= ((unsigned long *)fp
)[0];
9360 *paddr
= ((unsigned long *)fp
)[1];
9366 #warning add arch specific rt_get_caller_pc()
9368 static int rt_get_caller_pc(unsigned long *paddr
,
9369 ucontext_t
*uc
, int level
)
9375 /* emit a run time error at position 'pc' */
9376 void rt_error(ucontext_t
*uc
, const char *fmt
, ...)
9383 fprintf(stderr
, "Runtime error: ");
9384 vfprintf(stderr
, fmt
, ap
);
9385 fprintf(stderr
, "\n");
9386 for(i
=0;i
<num_callers
;i
++) {
9387 if (rt_get_caller_pc(&pc
, uc
, i
) < 0)
9390 fprintf(stderr
, "at ");
9392 fprintf(stderr
, "by ");
9399 /* signal handler for fatal errors */
9400 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
9402 ucontext_t
*uc
= puc
;
9406 switch(siginf
->si_code
) {
9409 rt_error(uc
, "division by zero");
9412 rt_error(uc
, "floating point exception");
9418 if (rt_bound_error_msg
&& *rt_bound_error_msg
)
9419 rt_error(uc
, *rt_bound_error_msg
);
9421 rt_error(uc
, "dereferencing invalid pointer");
9424 rt_error(uc
, "illegal instruction");
9427 rt_error(uc
, "abort() called");
9430 rt_error(uc
, "caught signal %d", signum
);
9437 /* do all relocations (needed before using tcc_get_symbol()) */
9438 int tcc_relocate(TCCState
*s1
)
9445 tcc_add_runtime(s1
);
9447 relocate_common_syms();
9449 tcc_add_linker_symbols(s1
);
9451 build_got_entries(s1
);
9453 /* compute relocation address : section are relocated in place. We
9454 also alloc the bss space */
9455 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9456 s
= s1
->sections
[i
];
9457 if (s
->sh_flags
& SHF_ALLOC
) {
9458 if (s
->sh_type
== SHT_NOBITS
)
9459 s
->data
= tcc_mallocz(s
->data_offset
);
9460 s
->sh_addr
= (unsigned long)s
->data
;
9464 relocate_syms(s1
, 1);
9466 if (s1
->nb_errors
!= 0)
9469 /* relocate each section */
9470 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9471 s
= s1
->sections
[i
];
9473 relocate_section(s1
, s
);
9478 /* launch the compiled program with the given arguments */
9479 int tcc_run(TCCState
*s1
, int argc
, char **argv
)
9481 int (*prog_main
)(int, char **);
9483 if (tcc_relocate(s1
) < 0)
9486 prog_main
= tcc_get_symbol_err(s1
, "main");
9489 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
9490 error("debug mode currently not available for Windows");
9492 struct sigaction sigact
;
9493 /* install TCC signal handlers to print debug info on fatal
9495 sigact
.sa_flags
= SA_SIGINFO
| SA_RESETHAND
;
9496 sigact
.sa_sigaction
= sig_error
;
9497 sigemptyset(&sigact
.sa_mask
);
9498 sigaction(SIGFPE
, &sigact
, NULL
);
9499 sigaction(SIGILL
, &sigact
, NULL
);
9500 sigaction(SIGSEGV
, &sigact
, NULL
);
9501 sigaction(SIGBUS
, &sigact
, NULL
);
9502 sigaction(SIGABRT
, &sigact
, NULL
);
9506 #ifdef CONFIG_TCC_BCHECK
9507 if (do_bounds_check
) {
9508 void (*bound_init
)(void);
9510 /* set error function */
9511 rt_bound_error_msg
= (void *)tcc_get_symbol_err(s1
,
9512 "__bound_error_msg");
9514 /* XXX: use .init section so that it also work in binary ? */
9515 bound_init
= (void *)tcc_get_symbol_err(s1
, "__bound_init");
9519 return (*prog_main
)(argc
, argv
);
9522 TCCState
*tcc_new(void)
9529 s
= tcc_mallocz(sizeof(TCCState
));
9533 s
->output_type
= TCC_OUTPUT_MEMORY
;
9535 /* init isid table */
9537 isidnum_table
[i
] = isid(i
) || isnum(i
);
9539 /* add all tokens */
9541 memset(hash_ident
, 0, TOK_HASH_SIZE
* sizeof(TokenSym
*));
9543 tok_ident
= TOK_IDENT
;
9552 ts
= tok_alloc(p
, r
- p
- 1);
9556 /* we add dummy defines for some special macros to speed up tests
9557 and to have working defined() */
9558 define_push(TOK___LINE__
, MACRO_OBJ
, NULL
, NULL
);
9559 define_push(TOK___FILE__
, MACRO_OBJ
, NULL
, NULL
);
9560 define_push(TOK___DATE__
, MACRO_OBJ
, NULL
, NULL
);
9561 define_push(TOK___TIME__
, MACRO_OBJ
, NULL
, NULL
);
9563 /* standard defines */
9564 tcc_define_symbol(s
, "__STDC__", NULL
);
9565 #if defined(TCC_TARGET_I386)
9566 tcc_define_symbol(s
, "__i386__", NULL
);
9568 #if defined(TCC_TARGET_ARM)
9569 tcc_define_symbol(s
, "__ARM_ARCH_4__", NULL
);
9570 tcc_define_symbol(s
, "__arm_elf__", NULL
);
9571 tcc_define_symbol(s
, "__arm_elf", NULL
);
9572 tcc_define_symbol(s
, "arm_elf", NULL
);
9573 tcc_define_symbol(s
, "__arm__", NULL
);
9574 tcc_define_symbol(s
, "__arm", NULL
);
9575 tcc_define_symbol(s
, "arm", NULL
);
9576 tcc_define_symbol(s
, "__APCS_32__", NULL
);
9579 tcc_define_symbol(s
, "__linux__", NULL
);
9580 tcc_define_symbol(s
, "linux", NULL
);
9582 /* tiny C specific defines */
9583 tcc_define_symbol(s
, "__TINYC__", NULL
);
9585 /* tiny C & gcc defines */
9586 tcc_define_symbol(s
, "__SIZE_TYPE__", "unsigned int");
9587 tcc_define_symbol(s
, "__PTRDIFF_TYPE__", "int");
9588 tcc_define_symbol(s
, "__WCHAR_TYPE__", "int");
9590 /* default library paths */
9591 tcc_add_library_path(s
, "/usr/local/lib");
9592 tcc_add_library_path(s
, "/usr/lib");
9593 tcc_add_library_path(s
, "/lib");
9595 /* no section zero */
9596 dynarray_add((void ***)&s
->sections
, &s
->nb_sections
, NULL
);
9598 /* create standard sections */
9599 text_section
= new_section(s
, ".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
9600 data_section
= new_section(s
, ".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
9601 bss_section
= new_section(s
, ".bss", SHT_NOBITS
, SHF_ALLOC
| SHF_WRITE
);
9603 /* symbols are always generated for linking stage */
9604 symtab_section
= new_symtab(s
, ".symtab", SHT_SYMTAB
, 0,
9606 ".hashtab", SHF_PRIVATE
);
9607 strtab_section
= symtab_section
->link
;
9609 /* private symbol table for dynamic symbols */
9610 s
->dynsymtab_section
= new_symtab(s
, ".dynsymtab", SHT_SYMTAB
, SHF_PRIVATE
,
9612 ".dynhashtab", SHF_PRIVATE
);
9613 s
->alacarte_link
= 1;
9615 #ifdef CHAR_IS_UNSIGNED
9616 s
->char_is_unsigned
= 1;
9621 void tcc_delete(TCCState
*s1
)
9625 /* free -D defines */
9629 n
= tok_ident
- TOK_IDENT
;
9630 for(i
= 0; i
< n
; i
++)
9631 tcc_free(table_ident
[i
]);
9632 tcc_free(table_ident
);
9634 /* free all sections */
9636 free_section(symtab_section
->hash
);
9638 free_section(s1
->dynsymtab_section
->hash
);
9639 free_section(s1
->dynsymtab_section
->link
);
9640 free_section(s1
->dynsymtab_section
);
9642 for(i
= 1; i
< s1
->nb_sections
; i
++)
9643 free_section(s1
->sections
[i
]);
9644 tcc_free(s1
->sections
);
9646 /* free loaded dlls array */
9647 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++)
9648 tcc_free(s1
->loaded_dlls
[i
]);
9649 tcc_free(s1
->loaded_dlls
);
9652 for(i
= 0; i
< s1
->nb_library_paths
; i
++)
9653 tcc_free(s1
->library_paths
[i
]);
9654 tcc_free(s1
->library_paths
);
9656 /* cached includes */
9657 for(i
= 0; i
< s1
->nb_cached_includes
; i
++)
9658 tcc_free(s1
->cached_includes
[i
]);
9659 tcc_free(s1
->cached_includes
);
9661 for(i
= 0; i
< s1
->nb_include_paths
; i
++)
9662 tcc_free(s1
->include_paths
[i
]);
9663 tcc_free(s1
->include_paths
);
9665 for(i
= 0; i
< s1
->nb_sysinclude_paths
; i
++)
9666 tcc_free(s1
->sysinclude_paths
[i
]);
9667 tcc_free(s1
->sysinclude_paths
);
9672 int tcc_add_include_path(TCCState
*s1
, const char *pathname
)
9676 pathname1
= tcc_strdup(pathname
);
9677 dynarray_add((void ***)&s1
->include_paths
, &s1
->nb_include_paths
, pathname1
);
9681 int tcc_add_sysinclude_path(TCCState
*s1
, const char *pathname
)
9685 pathname1
= tcc_strdup(pathname
);
9686 dynarray_add((void ***)&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
, pathname1
);
9690 static int tcc_add_file_internal(TCCState
*s1
, const char *filename
, int flags
)
9692 const char *ext
, *filename1
;
9695 BufferedFile
*saved_file
;
9697 /* find source file type with extension */
9698 filename1
= strrchr(filename
, '/');
9702 filename1
= filename
;
9703 ext
= strrchr(filename1
, '.');
9709 file
= tcc_open(s1
, filename
);
9711 if (flags
& AFF_PRINT_ERROR
) {
9712 error_noabort("file '%s' not found", filename
);
9718 if (!ext
|| !strcmp(ext
, "c")) {
9719 /* C file assumed */
9720 ret
= tcc_compile(s1
);
9722 #ifdef CONFIG_TCC_ASM
9723 if (!strcmp(ext
, "S")) {
9724 /* preprocessed assembler */
9725 ret
= tcc_assemble(s1
, 1);
9726 } else if (!strcmp(ext
, "s")) {
9727 /* non preprocessed assembler */
9728 ret
= tcc_assemble(s1
, 0);
9733 /* assume executable format: auto guess file type */
9734 ret
= read(fd
, &ehdr
, sizeof(ehdr
));
9735 lseek(fd
, 0, SEEK_SET
);
9737 error_noabort("could not read header");
9739 } else if (ret
!= sizeof(ehdr
)) {
9740 goto try_load_script
;
9743 if (ehdr
.e_ident
[0] == ELFMAG0
&&
9744 ehdr
.e_ident
[1] == ELFMAG1
&&
9745 ehdr
.e_ident
[2] == ELFMAG2
&&
9746 ehdr
.e_ident
[3] == ELFMAG3
) {
9747 file
->line_num
= 0; /* do not display line number if error */
9748 if (ehdr
.e_type
== ET_REL
) {
9749 ret
= tcc_load_object_file(s1
, fd
, 0);
9750 } else if (ehdr
.e_type
== ET_DYN
) {
9751 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
9753 h
= dlopen(filename
, RTLD_GLOBAL
| RTLD_LAZY
);
9759 ret
= tcc_load_dll(s1
, fd
, filename
,
9760 (flags
& AFF_REFERENCED_DLL
) != 0);
9763 error_noabort("unrecognized ELF file");
9766 } else if (memcmp((char *)&ehdr
, ARMAG
, 8) == 0) {
9767 file
->line_num
= 0; /* do not display line number if error */
9768 ret
= tcc_load_archive(s1
, fd
);
9770 #ifdef TCC_TARGET_COFF
9771 if (*(uint16_t *)(&ehdr
) == COFF_C67_MAGIC
) {
9772 ret
= tcc_load_coff(s1
, fd
);
9776 /* as GNU ld, consider it is an ld script if not recognized */
9778 ret
= tcc_load_ldscript(s1
);
9780 error_noabort("unrecognized file type");
9795 int tcc_add_file(TCCState
*s
, const char *filename
)
9797 return tcc_add_file_internal(s
, filename
, AFF_PRINT_ERROR
);
9800 int tcc_add_library_path(TCCState
*s
, const char *pathname
)
9804 pathname1
= tcc_strdup(pathname
);
9805 dynarray_add((void ***)&s
->library_paths
, &s
->nb_library_paths
, pathname1
);
9809 /* find and load a dll. Return non zero if not found */
9810 /* XXX: add '-rpath' option support ? */
9811 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
)
9816 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
9817 snprintf(buf
, sizeof(buf
), "%s/%s",
9818 s
->library_paths
[i
], filename
);
9819 if (tcc_add_file_internal(s
, buf
, flags
) == 0)
9825 /* the library name is the same as the argument of the '-l' option */
9826 int tcc_add_library(TCCState
*s
, const char *libraryname
)
9831 /* first we look for the dynamic library if not static linking */
9832 if (!s
->static_link
) {
9833 snprintf(buf
, sizeof(buf
), "lib%s.so", libraryname
);
9834 if (tcc_add_dll(s
, buf
, 0) == 0)
9838 /* then we look for the static library */
9839 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
9840 snprintf(buf
, sizeof(buf
), "%s/lib%s.a",
9841 s
->library_paths
[i
], libraryname
);
9842 if (tcc_add_file_internal(s
, buf
, 0) == 0)
9848 int tcc_add_symbol(TCCState
*s
, const char *name
, unsigned long val
)
9850 add_elf_sym(symtab_section
, val
, 0,
9851 ELF32_ST_INFO(STB_GLOBAL
, STT_NOTYPE
),
9856 int tcc_set_output_type(TCCState
*s
, int output_type
)
9860 s
->output_type
= output_type
;
9863 /* default include paths */
9864 /* XXX: reverse order needed if -isystem support */
9865 tcc_add_sysinclude_path(s
, "/usr/local/include");
9866 tcc_add_sysinclude_path(s
, "/usr/include");
9867 snprintf(buf
, sizeof(buf
), "%s/include", tcc_lib_path
);
9868 tcc_add_sysinclude_path(s
, buf
);
9871 /* if bound checking, then add corresponding sections */
9872 #ifdef CONFIG_TCC_BCHECK
9873 if (do_bounds_check
) {
9875 tcc_define_symbol(s
, "__BOUNDS_CHECKING_ON", NULL
);
9876 /* create bounds sections */
9877 bounds_section
= new_section(s
, ".bounds",
9878 SHT_PROGBITS
, SHF_ALLOC
);
9879 lbounds_section
= new_section(s
, ".lbounds",
9880 SHT_PROGBITS
, SHF_ALLOC
);
9884 if (s
->char_is_unsigned
) {
9885 tcc_define_symbol(s
, "__CHAR_UNSIGNED__", NULL
);
9888 /* add debug sections */
9891 stab_section
= new_section(s
, ".stab", SHT_PROGBITS
, 0);
9892 stab_section
->sh_entsize
= sizeof(Stab_Sym
);
9893 stabstr_section
= new_section(s
, ".stabstr", SHT_STRTAB
, 0);
9894 put_elf_str(stabstr_section
, "");
9895 stab_section
->link
= stabstr_section
;
9896 /* put first entry */
9897 put_stabs("", 0, 0, 0, 0);
9900 /* add libc crt1/crti objects */
9901 if ((output_type
== TCC_OUTPUT_EXE
|| output_type
== TCC_OUTPUT_DLL
) &&
9903 if (output_type
!= TCC_OUTPUT_DLL
)
9904 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crt1.o");
9905 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crti.o");
9910 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
9911 #define FD_INVERT 0x0002 /* invert value before storing */
9913 typedef struct FlagDef
{
9919 static const FlagDef warning_defs
[] = {
9920 { offsetof(TCCState
, warn_unsupported
), 0, "unsupported" },
9921 { offsetof(TCCState
, warn_write_strings
), 0, "write-strings" },
9922 { offsetof(TCCState
, warn_error
), 0, "error" },
9923 { offsetof(TCCState
, warn_implicit_function_declaration
), WD_ALL
,
9924 "implicit-function-declaration" },
9927 static int set_flag(TCCState
*s
, const FlagDef
*flags
, int nb_flags
,
9928 const char *name
, int value
)
9935 if (r
[0] == 'n' && r
[1] == 'o' && r
[2] == '-') {
9939 for(i
= 0, p
= flags
; i
< nb_flags
; i
++, p
++) {
9940 if (!strcmp(r
, p
->name
))
9945 if (p
->flags
& FD_INVERT
)
9947 *(int *)((uint8_t *)s
+ p
->offset
) = value
;
9952 /* set/reset a warning */
9953 int tcc_set_warning(TCCState
*s
, const char *warning_name
, int value
)
9958 if (!strcmp(warning_name
, "all")) {
9959 for(i
= 0, p
= warning_defs
; i
< countof(warning_defs
); i
++, p
++) {
9960 if (p
->flags
& WD_ALL
)
9961 *(int *)((uint8_t *)s
+ p
->offset
) = 1;
9965 return set_flag(s
, warning_defs
, countof(warning_defs
),
9966 warning_name
, value
);
9970 static const FlagDef flag_defs
[] = {
9971 { offsetof(TCCState
, char_is_unsigned
), 0, "unsigned-char" },
9972 { offsetof(TCCState
, char_is_unsigned
), FD_INVERT
, "signed-char" },
9973 { offsetof(TCCState
, nocommon
), FD_INVERT
, "common" },
9976 /* set/reset a flag */
9977 int tcc_set_flag(TCCState
*s
, const char *flag_name
, int value
)
9979 return set_flag(s
, flag_defs
, countof(flag_defs
),
9983 #if !defined(LIBTCC)
9985 /* extract the basename of a file */
9986 static const char *tcc_basename(const char *name
)
9989 p
= strrchr(name
, '/');
9992 p
= strrchr(name
, '\\');
10001 static int64_t getclock_us(void)
10006 return (tb
.time
* 1000LL + tb
.millitm
) * 1000LL;
10009 gettimeofday(&tv
, NULL
);
10010 return tv
.tv_sec
* 1000000LL + tv
.tv_usec
;
10016 printf("tcc version " TCC_VERSION
" - Tiny C Compiler - Copyright (C) 2001-2004 Fabrice Bellard\n"
10017 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10018 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10019 " [infile1 infile2...] [-run infile args...]\n"
10021 "General options:\n"
10022 " -v display current version\n"
10023 " -c compile only - generate an object file\n"
10024 " -o outfile set output filename\n"
10025 " -Bdir set tcc internal library path\n"
10026 " -bench output compilation statistics\n"
10027 " -run run compiled source\n"
10028 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10029 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10030 " -w disable all warnings\n"
10031 "Preprocessor options:\n"
10032 " -Idir add include path 'dir'\n"
10033 " -Dsym[=val] define 'sym' with value 'val'\n"
10034 " -Usym undefine 'sym'\n"
10035 "Linker options:\n"
10036 " -Ldir add library path 'dir'\n"
10037 " -llib link with dynamic or static library 'lib'\n"
10038 " -shared generate a shared library\n"
10039 " -static static linking\n"
10040 " -rdynamic export all global symbols to dynamic linker\n"
10041 " -r relocatable output\n"
10042 "Debugger options:\n"
10043 " -g generate runtime debug info\n"
10044 #ifdef CONFIG_TCC_BCHECK
10045 " -b compile with built-in memory and bounds checker (implies -g)\n"
10047 " -bt N show N callers in stack traces\n"
10051 #define TCC_OPTION_HAS_ARG 0x0001
10052 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10054 typedef struct TCCOption
{
10082 TCC_OPTION_nostdinc
,
10083 TCC_OPTION_nostdlib
,
10084 TCC_OPTION_print_search_dirs
,
10085 TCC_OPTION_rdynamic
,
10091 static const TCCOption tcc_options
[] = {
10092 { "h", TCC_OPTION_HELP
, 0 },
10093 { "?", TCC_OPTION_HELP
, 0 },
10094 { "I", TCC_OPTION_I
, TCC_OPTION_HAS_ARG
},
10095 { "D", TCC_OPTION_D
, TCC_OPTION_HAS_ARG
},
10096 { "U", TCC_OPTION_U
, TCC_OPTION_HAS_ARG
},
10097 { "L", TCC_OPTION_L
, TCC_OPTION_HAS_ARG
},
10098 { "B", TCC_OPTION_B
, TCC_OPTION_HAS_ARG
},
10099 { "l", TCC_OPTION_l
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10100 { "bench", TCC_OPTION_bench
, 0 },
10101 { "bt", TCC_OPTION_bt
, TCC_OPTION_HAS_ARG
},
10102 #ifdef CONFIG_TCC_BCHECK
10103 { "b", TCC_OPTION_b
, 0 },
10105 { "g", TCC_OPTION_g
, 0 },
10106 { "c", TCC_OPTION_c
, 0 },
10107 { "static", TCC_OPTION_static
, 0 },
10108 { "shared", TCC_OPTION_shared
, 0 },
10109 { "o", TCC_OPTION_o
, TCC_OPTION_HAS_ARG
},
10110 { "run", TCC_OPTION_run
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10111 { "rdynamic", TCC_OPTION_rdynamic
, 0 },
10112 { "r", TCC_OPTION_r
, 0 },
10113 { "Wl,", TCC_OPTION_Wl
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10114 { "W", TCC_OPTION_W
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10115 { "O", TCC_OPTION_O
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10116 { "m", TCC_OPTION_m
, TCC_OPTION_HAS_ARG
},
10117 { "f", TCC_OPTION_f
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10118 { "nostdinc", TCC_OPTION_nostdinc
, 0 },
10119 { "nostdlib", TCC_OPTION_nostdlib
, 0 },
10120 { "print-search-dirs", TCC_OPTION_print_search_dirs
, 0 },
10121 { "v", TCC_OPTION_v
, 0 },
10122 { "w", TCC_OPTION_w
, 0 },
10126 /* convert 'str' into an array of space separated strings */
10127 static int expand_args(char ***pargv
, const char *str
)
10136 while (is_space(*str
))
10141 while (*str
!= '\0' && !is_space(*str
))
10144 arg
= tcc_malloc(len
+ 1);
10145 memcpy(arg
, s1
, len
);
10147 dynarray_add((void ***)&argv
, &argc
, arg
);
10153 static char **files
;
10154 static int nb_files
, nb_libraries
;
10155 static int multiple_files
;
10156 static int print_search_dirs
;
10157 static int output_type
;
10158 static int reloc_output
;
10159 static const char *outfile
;
10161 int parse_args(TCCState
*s
, int argc
, char **argv
)
10164 const TCCOption
*popt
;
10165 const char *optarg
, *p1
, *r1
;
10170 if (optind
>= argc
) {
10171 if (nb_files
== 0 && !print_search_dirs
)
10176 r
= argv
[optind
++];
10178 /* add a new file */
10179 dynarray_add((void ***)&files
, &nb_files
, r
);
10180 if (!multiple_files
) {
10182 /* argv[0] will be this file */
10186 /* find option in table (match only the first chars */
10187 popt
= tcc_options
;
10191 error("invalid option -- '%s'", r
);
10204 if (popt
->flags
& TCC_OPTION_HAS_ARG
) {
10205 if (*r1
!= '\0' || (popt
->flags
& TCC_OPTION_NOSEP
)) {
10208 if (optind
>= argc
)
10209 error("argument to '%s' is missing", r
);
10210 optarg
= argv
[optind
++];
10218 switch(popt
->index
) {
10219 case TCC_OPTION_HELP
:
10224 if (tcc_add_include_path(s
, optarg
) < 0)
10225 error("too many include paths");
10230 sym
= (char *)optarg
;
10231 value
= strchr(sym
, '=');
10236 tcc_define_symbol(s
, sym
, value
);
10240 tcc_undefine_symbol(s
, optarg
);
10243 tcc_add_library_path(s
, optarg
);
10246 /* set tcc utilities path (mainly for tcc development) */
10247 tcc_lib_path
= optarg
;
10250 dynarray_add((void ***)&files
, &nb_files
, r
);
10253 case TCC_OPTION_bench
:
10256 case TCC_OPTION_bt
:
10257 num_callers
= atoi(optarg
);
10259 #ifdef CONFIG_TCC_BCHECK
10261 do_bounds_check
= 1;
10269 multiple_files
= 1;
10270 output_type
= TCC_OUTPUT_OBJ
;
10272 case TCC_OPTION_static
:
10273 s
->static_link
= 1;
10275 case TCC_OPTION_shared
:
10276 output_type
= TCC_OUTPUT_DLL
;
10279 multiple_files
= 1;
10283 /* generate a .o merging several output files */
10285 output_type
= TCC_OUTPUT_OBJ
;
10287 case TCC_OPTION_nostdinc
:
10290 case TCC_OPTION_nostdlib
:
10293 case TCC_OPTION_print_search_dirs
:
10294 print_search_dirs
= 1;
10296 case TCC_OPTION_run
:
10300 argc1
= expand_args(&argv1
, optarg
);
10302 parse_args(s
, argc1
, argv1
);
10304 multiple_files
= 0;
10305 output_type
= TCC_OUTPUT_MEMORY
;
10309 printf("tcc version %s\n", TCC_VERSION
);
10312 if (tcc_set_flag(s
, optarg
, 1) < 0 && s
->warn_unsupported
)
10313 goto unsupported_option
;
10316 if (tcc_set_warning(s
, optarg
, 1) < 0 &&
10317 s
->warn_unsupported
)
10318 goto unsupported_option
;
10323 case TCC_OPTION_rdynamic
:
10326 case TCC_OPTION_Wl
:
10329 if (strstart(optarg
, "-Ttext,", &p
)) {
10330 s
->text_addr
= strtoul(p
, NULL
, 16);
10331 s
->has_text_addr
= 1;
10332 } else if (strstart(optarg
, "--oformat,", &p
)) {
10333 if (strstart(p
, "elf32-", NULL
)) {
10334 s
->output_format
= TCC_OUTPUT_FORMAT_ELF
;
10335 } else if (!strcmp(p
, "binary")) {
10336 s
->output_format
= TCC_OUTPUT_FORMAT_BINARY
;
10338 #ifdef TCC_TARGET_COFF
10339 if (!strcmp(p
, "coff")) {
10340 s
->output_format
= TCC_OUTPUT_FORMAT_COFF
;
10344 error("target %s not found", p
);
10347 error("unsupported linker option '%s'", optarg
);
10352 if (s
->warn_unsupported
) {
10353 unsupported_option
:
10354 warning("unsupported option '%s'", r
);
10363 int main(int argc
, char **argv
)
10367 int nb_objfiles
, ret
, optind
;
10368 char objfilename
[1024];
10369 int64_t start_time
= 0;
10372 output_type
= TCC_OUTPUT_EXE
;
10374 multiple_files
= 1;
10379 print_search_dirs
= 0;
10381 optind
= parse_args(s
, argc
- 1, argv
+ 1) + 1;
10383 if (print_search_dirs
) {
10384 /* enough for Linux kernel */
10385 printf("install: %s/\n", tcc_lib_path
);
10389 nb_objfiles
= nb_files
- nb_libraries
;
10391 /* if outfile provided without other options, we output an
10393 if (outfile
&& output_type
== TCC_OUTPUT_MEMORY
)
10394 output_type
= TCC_OUTPUT_EXE
;
10396 /* check -c consistency : only single file handled. XXX: checks file type */
10397 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
10398 /* accepts only a single input file */
10399 if (nb_objfiles
!= 1)
10400 error("cannot specify multiple files with -c");
10401 if (nb_libraries
!= 0)
10402 error("cannot specify libraries with -c");
10405 /* compute default outfile name */
10406 if (output_type
!= TCC_OUTPUT_MEMORY
&& !outfile
) {
10407 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
10410 pstrcpy(objfilename
, sizeof(objfilename
) - 1,
10411 tcc_basename(files
[0]));
10412 /* add .o extension */
10413 ext
= strrchr(objfilename
, '.');
10415 goto default_outfile
;
10416 strcpy(ext
+ 1, "o");
10419 pstrcpy(objfilename
, sizeof(objfilename
), "a.out");
10421 outfile
= objfilename
;
10425 start_time
= getclock_us();
10428 tcc_set_output_type(s
, output_type
);
10430 /* compile or add each files or library */
10431 for(i
= 0;i
< nb_files
; i
++) {
10432 const char *filename
;
10434 filename
= files
[i
];
10435 if (filename
[0] == '-') {
10436 if (tcc_add_library(s
, filename
+ 2) < 0)
10437 error("cannot find %s", filename
);
10439 if (tcc_add_file(s
, filename
) < 0) {
10446 /* free all files */
10451 total_time
= (double)(getclock_us() - start_time
) / 1000000.0;
10452 if (total_time
< 0.001)
10453 total_time
= 0.001;
10454 if (total_bytes
< 1)
10456 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10457 tok_ident
- TOK_IDENT
, total_lines
, total_bytes
,
10458 total_time
, (int)(total_lines
/ total_time
),
10459 total_bytes
/ total_time
/ 1000000.0);
10462 if (s
->output_type
!= TCC_OUTPUT_MEMORY
) {
10463 tcc_output_file(s
, outfile
);
10466 ret
= tcc_run(s
, argc
- optind
, argv
+ optind
);
10469 /* XXX: cannot do it with bound checking because of the malloc hooks */
10470 if (!do_bounds_check
)
10475 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size
, mem_max_size
);