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
42 #include <sys/timeb.h>
43 // #include <windows.h>
47 #include <sys/ucontext.h>
51 #endif /* !CONFIG_TCCBOOT */
68 /* preprocessor debug */
70 /* include file debug */
78 /* target selection */
79 //#define TCC_TARGET_I386 /* i386 code generator */
80 //#define TCC_TARGET_ARM /* ARMv4 code generator */
81 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
83 /* default target is I386 */
84 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
85 !defined(TCC_TARGET_C67)
86 #define TCC_TARGET_I386
89 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
90 !defined(TCC_TARGET_C67)
91 #define CONFIG_TCC_BCHECK /* enable bound checking code */
94 #if defined(WIN32) && !defined(TCC_TARGET_PE)
95 #define CONFIG_TCC_STATIC
98 /* define it to include assembler support */
99 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
100 #define CONFIG_TCC_ASM
103 /* object format selection */
104 #if defined(TCC_TARGET_C67)
105 #define TCC_TARGET_COFF
114 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
115 executables or dlls */
116 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
118 #define INCLUDE_STACK_SIZE 32
119 #define IFDEF_STACK_SIZE 64
120 #define VSTACK_SIZE 256
121 #define STRING_MAX_SIZE 1024
122 #define PACK_STACK_SIZE 8
124 #define TOK_HASH_SIZE 8192 /* must be a power of two */
125 #define TOK_ALLOC_INCR 512 /* must be a power of two */
126 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
128 /* token symbol management */
129 typedef struct TokenSym
{
130 struct TokenSym
*hash_next
;
131 struct Sym
*sym_define
; /* direct pointer to define */
132 struct Sym
*sym_label
; /* direct pointer to label */
133 struct Sym
*sym_struct
; /* direct pointer to structure */
134 struct Sym
*sym_identifier
; /* direct pointer to identifier */
135 int tok
; /* token number */
141 typedef unsigned short nwchar_t
;
143 typedef int nwchar_t
;
146 typedef struct CString
{
147 int size
; /* size in bytes */
148 void *data
; /* either 'char *' or 'nwchar_t *' */
150 void *data_allocated
; /* if non NULL, data has been malloced */
153 /* type definition */
154 typedef struct CType
{
160 typedef union CValue
{
166 unsigned int ul
; /* address (should be unsigned long on 64 bit cpu) */
168 unsigned long long ull
;
169 struct CString
*cstr
;
175 typedef struct SValue
{
176 CType type
; /* type */
177 unsigned short r
; /* register + flags */
178 unsigned short r2
; /* second register, used for 'long long'
179 type. If not used, set to VT_CONST */
180 CValue c
; /* constant, if VT_CONST */
181 struct Sym
*sym
; /* symbol, if (VT_SYM | VT_CONST) */
184 /* symbol management */
186 int v
; /* symbol token */
187 int r
; /* associated register */
188 int c
; /* associated number */
189 CType type
; /* associated type */
190 struct Sym
*next
; /* next related symbol */
191 struct Sym
*prev
; /* prev symbol in stack */
192 struct Sym
*prev_tok
; /* previous symbol for this token */
195 /* section definition */
196 /* XXX: use directly ELF structure for parameters ? */
197 /* special flag to indicate that the section should not be linked to
199 #define SHF_PRIVATE 0x80000000
201 typedef struct Section
{
202 unsigned long data_offset
; /* current data offset */
203 unsigned char *data
; /* section data */
204 unsigned long data_allocated
; /* used for realloc() handling */
205 int sh_name
; /* elf section name (only used during output) */
206 int sh_num
; /* elf section number */
207 int sh_type
; /* elf section type */
208 int sh_flags
; /* elf section flags */
209 int sh_info
; /* elf section info */
210 int sh_addralign
; /* elf section alignment */
211 int sh_entsize
; /* elf entry size */
212 unsigned long sh_size
; /* section size (only used during output) */
213 unsigned long sh_addr
; /* address at which the section is relocated */
214 unsigned long sh_offset
; /* file offset */
215 int nb_hashed_syms
; /* used to resize the hash table */
216 struct Section
*link
; /* link to another section */
217 struct Section
*reloc
; /* corresponding section for relocation, if any */
218 struct Section
*hash
; /* hash table for symbols */
219 struct Section
*next
;
220 char name
[1]; /* section name */
223 typedef struct DLLReference
{
228 /* GNUC attribute definition */
229 typedef struct AttributeDef
{
233 unsigned char func_call
; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
234 unsigned char dllexport
;
237 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
238 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
239 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
241 /* stored in 'Sym.c' field */
242 #define FUNC_NEW 1 /* ansi function prototype */
243 #define FUNC_OLD 2 /* old function prototype */
244 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
246 /* stored in 'Sym.r' field */
247 #define FUNC_CDECL 0 /* standard c call */
248 #define FUNC_STDCALL 1 /* pascal c call */
249 #define FUNC_FASTCALL1 2 /* first param in %eax */
250 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
251 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
252 #define FUNC_FASTCALLW 5 /* first parameter in %ecx, %edx */
254 /* field 'Sym.t' for macros */
255 #define MACRO_OBJ 0 /* object like macro */
256 #define MACRO_FUNC 1 /* function like macro */
258 /* field 'Sym.r' for C labels */
259 #define LABEL_DEFINED 0 /* label is defined */
260 #define LABEL_FORWARD 1 /* label is forward defined */
261 #define LABEL_DECLARED 2 /* label is declared but never used */
263 /* type_decl() types */
264 #define TYPE_ABSTRACT 1 /* type without variable */
265 #define TYPE_DIRECT 2 /* type with variable */
267 #define IO_BUF_SIZE 8192
269 typedef struct BufferedFile
{
273 int line_num
; /* current line number - here to simplify code */
274 int ifndef_macro
; /* #ifndef macro / #endif search */
275 int ifndef_macro_saved
; /* saved ifndef_macro */
276 int *ifdef_stack_ptr
; /* ifdef_stack value at the start of the file */
277 char inc_type
; /* type of include */
278 char inc_filename
[512]; /* filename specified by the user */
279 char filename
[1024]; /* current filename - here to simplify code */
280 unsigned char buffer
[IO_BUF_SIZE
+ 1]; /* extra size for CH_EOB char */
283 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
284 #define CH_EOF (-1) /* end of file */
286 /* parsing state (used to save parser state to reparse part of the
287 source several times) */
288 typedef struct ParseState
{
295 /* used to record tokens */
296 typedef struct TokenString
{
303 /* include file cache, used to find files faster and also to eliminate
304 inclusion if the include file is protected by #ifndef ... #endif */
305 typedef struct CachedInclude
{
307 int hash_next
; /* -1 if none */
308 char type
; /* '"' or '>' to give include type */
309 char filename
[1]; /* path specified in #include */
312 #define CACHED_INCLUDES_HASH_SIZE 512
315 static struct BufferedFile
*file
;
318 static CString tokcstr
; /* current parsed string, if any */
319 /* additional informations about token */
320 static int tok_flags
;
321 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
322 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
323 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
324 #define TOK_FLAG_EOF 0x0008 /* end of file */
326 static int *macro_ptr
, *macro_ptr_allocated
;
327 static int *unget_saved_macro_ptr
;
328 static int unget_saved_buffer
[TOK_MAX_SIZE
+ 1];
329 static int unget_buffer_enabled
;
330 static int parse_flags
;
331 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
332 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
333 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
334 token. line feed is also
336 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
338 static Section
*text_section
, *data_section
, *bss_section
; /* predefined sections */
339 static Section
*cur_text_section
; /* current section where function code is
341 #ifdef CONFIG_TCC_ASM
342 static Section
*last_text_section
; /* to handle .previous asm directive */
344 /* bound check related sections */
345 static Section
*bounds_section
; /* contains global data bound description */
346 static Section
*lbounds_section
; /* contains local data bound description */
347 /* symbol sections */
348 static Section
*symtab_section
, *strtab_section
;
351 static Section
*stab_section
, *stabstr_section
;
353 /* loc : local variable index
354 ind : output code index
356 anon_sym: anonymous symbol index
358 static int rsym
, anon_sym
, ind
, loc
;
359 /* expression generation modifiers */
360 static int const_wanted
; /* true if constant wanted */
361 static int nocode_wanted
; /* true if no code generation wanted for an expression */
362 static int global_expr
; /* true if compound literals must be allocated
363 globally (used during initializers parsing */
364 static CType func_vt
; /* current function return type (used by return
367 static int last_line_num
, last_ind
, func_ind
; /* debug last line number and pc */
368 static int tok_ident
;
369 static TokenSym
**table_ident
;
370 static TokenSym
*hash_ident
[TOK_HASH_SIZE
];
371 static char token_buf
[STRING_MAX_SIZE
+ 1];
372 static char *funcname
;
373 static Sym
*global_stack
, *local_stack
;
374 static Sym
*define_stack
;
375 static Sym
*global_label_stack
, *local_label_stack
;
376 /* symbol allocator */
377 #define SYM_POOL_NB (8192 / sizeof(Sym))
378 static Sym
*sym_free_first
;
380 static SValue vstack
[VSTACK_SIZE
], *vtop
;
381 /* some predefined types */
382 static CType char_pointer_type
, func_old_type
, int_type
;
383 /* true if isid(c) || isnum(c) */
384 static unsigned char isidnum_table
[256];
386 /* compile with debug symbol (and use them if error during execution) */
387 static int do_debug
= 0;
389 /* compile with built-in memory and bounds checker */
390 static int do_bounds_check
= 0;
392 /* display benchmark infos */
394 static int do_bench
= 0;
396 static int total_lines
;
397 static int total_bytes
;
399 /* use GNU C extensions */
400 static int gnu_ext
= 1;
402 /* use Tiny C extensions */
403 static int tcc_ext
= 1;
405 /* max number of callers shown if error */
406 static int num_callers
= 6;
407 static const char **rt_bound_error_msg
;
409 /* XXX: get rid of this ASAP */
410 static struct TCCState
*tcc_state
;
412 /* give the path of the tcc libraries */
413 static const char *tcc_lib_path
= CONFIG_TCCDIR
;
418 BufferedFile
**include_stack_ptr
;
419 int *ifdef_stack_ptr
;
421 /* include file handling */
422 char **include_paths
;
423 int nb_include_paths
;
424 char **sysinclude_paths
;
425 int nb_sysinclude_paths
;
426 CachedInclude
**cached_includes
;
427 int nb_cached_includes
;
429 char **library_paths
;
430 int nb_library_paths
;
432 /* array of all loaded dlls (including those referenced by loaded
434 DLLReference
**loaded_dlls
;
439 int nb_sections
; /* number of sections, including first dummy section */
444 unsigned long *got_offsets
;
446 /* give the correspondance from symtab indexes to dynsym indexes */
447 int *symtab_to_dynsym
;
449 /* temporary dynamic symbol sections (for dll loading) */
450 Section
*dynsymtab_section
;
451 /* exported dynamic symbol section */
454 int nostdinc
; /* if true, no standard headers are added */
455 int nostdlib
; /* if true, no standard libraries are added */
457 int nocommon
; /* if true, do not use common symbols for .bss data */
459 /* if true, static linking is performed */
462 /* if true, all symbols are exported */
465 /* if true, only link in referenced objects from archive */
468 /* address of text section */
469 unsigned long text_addr
;
472 /* output format, see TCC_OUTPUT_FORMAT_xxx */
475 /* C language options */
476 int char_is_unsigned
;
477 int leading_underscore
;
479 /* warning switches */
480 int warn_write_strings
;
481 int warn_unsupported
;
484 int warn_implicit_function_declaration
;
488 void (*error_func
)(void *opaque
, const char *msg
);
489 int error_set_jmp_enabled
;
490 jmp_buf error_jmp_buf
;
493 /* tiny assembler state */
496 /* see include_stack_ptr */
497 BufferedFile
*include_stack
[INCLUDE_STACK_SIZE
];
499 /* see ifdef_stack_ptr */
500 int ifdef_stack
[IFDEF_STACK_SIZE
];
502 /* see cached_includes */
503 int cached_includes_hash
[CACHED_INCLUDES_HASH_SIZE
];
506 int pack_stack
[PACK_STACK_SIZE
];
509 /* output file for preprocessing */
513 /* The current value can be: */
514 #define VT_VALMASK 0x00ff
515 #define VT_CONST 0x00f0 /* constant in vc
516 (must be first non register value) */
517 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
518 #define VT_LOCAL 0x00f2 /* offset on stack */
519 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
520 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
521 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
522 #define VT_LVAL 0x0100 /* var is an lvalue */
523 #define VT_SYM 0x0200 /* a symbol value is added */
524 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
525 char/short stored in integer registers) */
526 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
527 dereferencing value */
528 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
529 bounding function call point is in vc */
530 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
531 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
532 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
533 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
536 #define VT_INT 0 /* integer type */
537 #define VT_BYTE 1 /* signed byte type */
538 #define VT_SHORT 2 /* short type */
539 #define VT_VOID 3 /* void type */
540 #define VT_PTR 4 /* pointer */
541 #define VT_ENUM 5 /* enum definition */
542 #define VT_FUNC 6 /* function type */
543 #define VT_STRUCT 7 /* struct/union definition */
544 #define VT_FLOAT 8 /* IEEE float */
545 #define VT_DOUBLE 9 /* IEEE double */
546 #define VT_LDOUBLE 10 /* IEEE long double */
547 #define VT_BOOL 11 /* ISOC99 boolean type */
548 #define VT_LLONG 12 /* 64 bit integer */
549 #define VT_LONG 13 /* long integer (NEVER USED as type, only
551 #define VT_BTYPE 0x000f /* mask for basic type */
552 #define VT_UNSIGNED 0x0010 /* unsigned type */
553 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
554 #define VT_BITFIELD 0x0040 /* bitfield modifier */
555 #define VT_CONSTANT 0x0800 /* const modifier */
556 #define VT_VOLATILE 0x1000 /* volatile modifier */
557 #define VT_SIGNED 0x2000 /* signed type */
560 #define VT_EXTERN 0x00000080 /* extern definition */
561 #define VT_STATIC 0x00000100 /* static variable */
562 #define VT_TYPEDEF 0x00000200 /* typedef definition */
563 #define VT_INLINE 0x00000400 /* inline definition */
565 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
567 /* type mask (except storage) */
568 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
569 #define VT_TYPE (~(VT_STORAGE))
573 /* warning: the following compare tokens depend on i386 asm code */
580 #define TOK_Nset 0x98
581 #define TOK_Nclear 0x99
587 #define TOK_LAND 0xa0
591 #define TOK_MID 0xa3 /* inc/dec, to void constant */
593 #define TOK_UDIV 0xb0 /* unsigned division */
594 #define TOK_UMOD 0xb1 /* unsigned modulo */
595 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
596 #define TOK_CINT 0xb3 /* number in tokc */
597 #define TOK_CCHAR 0xb4 /* char constant in tokc */
598 #define TOK_STR 0xb5 /* pointer to string in tokc */
599 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
600 #define TOK_LCHAR 0xb7
601 #define TOK_LSTR 0xb8
602 #define TOK_CFLOAT 0xb9 /* float constant */
603 #define TOK_LINENUM 0xba /* line number info */
604 #define TOK_CDOUBLE 0xc0 /* double constant */
605 #define TOK_CLDOUBLE 0xc1 /* long double constant */
606 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
607 #define TOK_ADDC1 0xc3 /* add with carry generation */
608 #define TOK_ADDC2 0xc4 /* add with carry use */
609 #define TOK_SUBC1 0xc5 /* add with carry generation */
610 #define TOK_SUBC2 0xc6 /* add with carry use */
611 #define TOK_CUINT 0xc8 /* unsigned int constant */
612 #define TOK_CLLONG 0xc9 /* long long constant */
613 #define TOK_CULLONG 0xca /* unsigned long long constant */
614 #define TOK_ARROW 0xcb
615 #define TOK_DOTS 0xcc /* three dots */
616 #define TOK_SHR 0xcd /* unsigned shift right */
617 #define TOK_PPNUM 0xce /* preprocessor number */
619 #define TOK_SHL 0x01 /* shift left */
620 #define TOK_SAR 0x02 /* signed shift right */
622 /* assignement operators : normal operator or 0x80 */
623 #define TOK_A_MOD 0xa5
624 #define TOK_A_AND 0xa6
625 #define TOK_A_MUL 0xaa
626 #define TOK_A_ADD 0xab
627 #define TOK_A_SUB 0xad
628 #define TOK_A_DIV 0xaf
629 #define TOK_A_XOR 0xde
630 #define TOK_A_OR 0xfc
631 #define TOK_A_SHL 0x81
632 #define TOK_A_SAR 0x82
635 #define offsetof(type, field) ((size_t) &((type *)0)->field)
639 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
642 /* WARNING: the content of this string encodes token numbers */
643 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";
645 #define TOK_EOF (-1) /* end of file */
646 #define TOK_LINEFEED 10 /* line feed */
648 /* all identificators and strings have token above that */
649 #define TOK_IDENT 256
651 /* only used for i386 asm opcodes definitions */
652 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
655 DEF(TOK_ASM_ ## x ## b, #x "b") \
656 DEF(TOK_ASM_ ## x ## w, #x "w") \
657 DEF(TOK_ASM_ ## x ## l, #x "l") \
658 DEF(TOK_ASM_ ## x, #x)
661 DEF(TOK_ASM_ ## x ## w, #x "w") \
662 DEF(TOK_ASM_ ## x ## l, #x "l") \
663 DEF(TOK_ASM_ ## x, #x)
666 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
667 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
668 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
669 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
672 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
673 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
676 #define DEF_ASMTEST(x) \
708 #define TOK_ASM_int TOK_INT
711 TOK_LAST
= TOK_IDENT
- 1,
712 #define DEF(id, str) id,
717 static const char tcc_keywords
[] =
718 #define DEF(id, str) str "\0"
723 #define TOK_UIDENT TOK_DEFINE
726 int __stdcall
GetModuleFileNameA(void *, char *, int);
727 void *__stdcall
GetProcAddress(void *, const char *);
728 void *__stdcall
GetModuleHandleA(const char *);
729 void *__stdcall
LoadLibraryA(const char *);
730 int __stdcall
FreeConsole(void);
731 int __stdcall
VirtualProtect(void*,unsigned long,unsigned long,unsigned long*);
732 #define PAGE_EXECUTE_READWRITE 0x0040
734 #define snprintf _snprintf
735 #define vsnprintf _vsnprintf
737 #define strtold (long double)strtod
738 #define strtof (float)strtod
739 #define strtoll (long long)strtol
741 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__)
742 /* currently incorrect */
743 long double strtold(const char *nptr
, char **endptr
)
745 return (long double)strtod(nptr
, endptr
);
747 float strtof(const char *nptr
, char **endptr
)
749 return (float)strtod(nptr
, endptr
);
752 /* XXX: need to define this to use them in non ISOC99 context */
753 extern float strtof (const char *__nptr
, char **__endptr
);
754 extern long double strtold (const char *__nptr
, char **__endptr
);
757 static char *pstrcpy(char *buf
, int buf_size
, const char *s
);
758 static char *pstrcat(char *buf
, int buf_size
, const char *s
);
759 static char *tcc_basename(const char *name
);
761 static void next(void);
762 static void next_nomacro(void);
763 static void parse_expr_type(CType
*type
);
764 static void expr_type(CType
*type
);
765 static void unary_type(CType
*type
);
766 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
767 int case_reg
, int is_expr
);
768 static int expr_const(void);
769 static void expr_eq(void);
770 static void gexpr(void);
771 static void gen_inline_functions(void);
772 static void decl(int l
);
773 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
774 int first
, int size_only
);
775 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
776 int has_init
, int v
, int scope
);
778 void gv2(int rc1
, int rc2
);
779 void move_reg(int r
, int s
);
780 void save_regs(int n
);
781 void save_reg(int r
);
786 int get_reg_ex(int rc
,int rc2
);
789 struct macro_level
*prev
;
793 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
794 const int *macro_str
, struct macro_level
**can_read_stream
);
796 void force_charshort_cast(int t
);
797 static void gen_cast(CType
*type
);
799 static Sym
*sym_find(int v
);
800 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
);
803 static int type_size(CType
*type
, int *a
);
804 static inline CType
*pointed_type(CType
*type
);
805 static int pointed_size(CType
*type
);
806 static int lvalue_type(int t
);
807 static int parse_btype(CType
*type
, AttributeDef
*ad
);
808 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
);
809 static int compare_types(CType
*type1
, CType
*type2
, int unqualified
);
810 static int is_compatible_types(CType
*type1
, CType
*type2
);
811 static int is_compatible_parameter_types(CType
*type1
, CType
*type2
);
813 int ieee_finite(double d
);
814 void error(const char *fmt
, ...);
818 void lexpand_nr(void);
819 static void vpush_global_sym(CType
*type
, int v
);
820 void vset(CType
*type
, int r
, int v
);
821 void type_to_str(char *buf
, int buf_size
,
822 CType
*type
, const char *varstr
);
823 char *get_tok_str(int v
, CValue
*cv
);
824 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
825 unsigned long offset
, unsigned long size
);
826 static Sym
*external_global_sym(int v
, CType
*type
, int r
);
828 /* section generation */
829 static void section_realloc(Section
*sec
, unsigned long new_size
);
830 static void *section_ptr_add(Section
*sec
, unsigned long size
);
831 static void put_extern_sym(Sym
*sym
, Section
*section
,
832 unsigned long value
, unsigned long size
);
833 static void greloc(Section
*s
, Sym
*sym
, unsigned long addr
, int type
);
834 static int put_elf_str(Section
*s
, const char *sym
);
835 static int put_elf_sym(Section
*s
,
836 unsigned long value
, unsigned long size
,
837 int info
, int other
, int shndx
, const char *name
);
838 static int add_elf_sym(Section
*s
, unsigned long value
, unsigned long size
,
839 int info
, int other
, int sh_num
, const char *name
);
840 static void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
841 int type
, int symbol
);
842 static void put_stabs(const char *str
, int type
, int other
, int desc
,
843 unsigned long value
);
844 static void put_stabs_r(const char *str
, int type
, int other
, int desc
,
845 unsigned long value
, Section
*sec
, int sym_index
);
846 static void put_stabn(int type
, int other
, int desc
, int value
);
847 static void put_stabd(int type
, int other
, int desc
);
848 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
);
850 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
851 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
852 #define AFF_PREPROCESS 0x0004 /* preprocess file */
853 static int tcc_add_file_internal(TCCState
*s
, const char *filename
, int flags
);
856 int tcc_output_coff(TCCState
*s1
, FILE *f
);
859 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
);
860 int pe_load_def_file(struct TCCState
*s1
, FILE *fp
);
861 void pe_setup_paths(struct TCCState
*s1
, int *p_output_type
, const char **p_outfile
, char *first_file
);
862 unsigned long pe_add_runtime(struct TCCState
*s1
);
863 int tcc_output_pe(struct TCCState
*s1
, const char *filename
);
867 #ifdef CONFIG_TCC_ASM
869 typedef struct ExprValue
{
874 #define MAX_ASM_OPERANDS 30
876 typedef struct ASMOperand
{
877 int id
; /* GCC 3 optionnal identifier (0 if number only supported */
879 char asm_str
[16]; /* computed asm string for operand */
880 SValue
*vt
; /* C value of the expression */
881 int ref_index
; /* if >= 0, gives reference to a output constraint */
882 int input_index
; /* if >= 0, gives reference to an input constraint */
883 int priority
; /* priority, used to assign registers */
884 int reg
; /* if >= 0, register number used for this operand */
885 int is_llong
; /* true if double register value */
886 int is_memory
; /* true if memory operand */
887 int is_rw
; /* for '+' modifier */
890 static void asm_expr(TCCState
*s1
, ExprValue
*pe
);
891 static int asm_int_expr(TCCState
*s1
);
892 static int find_constraint(ASMOperand
*operands
, int nb_operands
,
893 const char *name
, const char **pp
);
895 static int tcc_assemble(TCCState
*s1
, int do_preprocess
);
899 static void asm_instr(void);
900 static void asm_global_instr(void);
902 /* true if float/double/long double type */
903 static inline int is_float(int t
)
907 return bt
== VT_LDOUBLE
|| bt
== VT_DOUBLE
|| bt
== VT_FLOAT
;
910 #ifdef TCC_TARGET_I386
911 #include "i386-gen.c"
914 #ifdef TCC_TARGET_ARM
918 #ifdef TCC_TARGET_C67
922 #ifdef CONFIG_TCC_STATIC
924 #define RTLD_LAZY 0x001
925 #define RTLD_NOW 0x002
926 #define RTLD_GLOBAL 0x100
927 #define RTLD_DEFAULT NULL
929 /* dummy function for profiling */
930 void *dlopen(const char *filename
, int flag
)
935 const char *dlerror(void)
940 typedef struct TCCSyms
{
945 #define TCCSYM(a) { #a, &a, },
947 /* add the symbol you want here if no dynamic linking is done */
948 static TCCSyms tcc_syms
[] = {
949 #if !defined(CONFIG_TCCBOOT)
958 void *resolve_sym(TCCState
*s1
, const char *symbol
, int type
)
962 while (p
->str
!= NULL
) {
963 if (!strcmp(p
->str
, symbol
))
970 #elif !defined(WIN32)
974 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
)
976 return dlsym(RTLD_DEFAULT
, sym
);
981 /********************************************************/
983 /* we use our own 'finite' function to avoid potential problems with
984 non standard math libs */
985 /* XXX: endianness dependent */
986 int ieee_finite(double d
)
989 return ((unsigned)((p
[1] | 0x800fffff) + 1)) >> 31;
992 /* copy a string and truncate it. */
993 static char *pstrcpy(char *buf
, int buf_size
, const char *s
)
1000 q_end
= buf
+ buf_size
- 1;
1012 /* strcat and truncate. */
1013 static char *pstrcat(char *buf
, int buf_size
, const char *s
)
1018 pstrcpy(buf
+ len
, buf_size
- len
, s
);
1022 static int strstart(const char *str
, const char *val
, const char **ptr
)
1027 while (*q
!= '\0') {
1039 char *normalize_slashes(char *path
)
1042 for (p
= path
; *p
; ++p
)
1048 char *w32_tcc_lib_path(void)
1050 /* on win32, we suppose the lib and includes are at the location
1052 char path
[1024], *p
;
1053 GetModuleFileNameA(NULL
, path
, sizeof path
);
1054 p
= tcc_basename(normalize_slashes(strlwr(path
)));
1055 if (p
- 5 > path
&& 0 == strncmp(p
- 5, "/bin/", 5))
1060 return strdup(path
);
1064 /* memory management */
1070 static inline void tcc_free(void *ptr
)
1073 mem_cur_size
-= malloc_usable_size(ptr
);
1078 static void *tcc_malloc(unsigned long size
)
1083 error("memory full");
1085 mem_cur_size
+= malloc_usable_size(ptr
);
1086 if (mem_cur_size
> mem_max_size
)
1087 mem_max_size
= mem_cur_size
;
1092 static void *tcc_mallocz(unsigned long size
)
1095 ptr
= tcc_malloc(size
);
1096 memset(ptr
, 0, size
);
1100 static inline void *tcc_realloc(void *ptr
, unsigned long size
)
1104 mem_cur_size
-= malloc_usable_size(ptr
);
1106 ptr1
= realloc(ptr
, size
);
1108 /* NOTE: count not correct if alloc error, but not critical */
1109 mem_cur_size
+= malloc_usable_size(ptr1
);
1110 if (mem_cur_size
> mem_max_size
)
1111 mem_max_size
= mem_cur_size
;
1116 static char *tcc_strdup(const char *str
)
1119 ptr
= tcc_malloc(strlen(str
) + 1);
1124 #define free(p) use_tcc_free(p)
1125 #define malloc(s) use_tcc_malloc(s)
1126 #define realloc(p, s) use_tcc_realloc(p, s)
1128 static void dynarray_add(void ***ptab
, int *nb_ptr
, void *data
)
1135 /* every power of two we double array size */
1136 if ((nb
& (nb
- 1)) == 0) {
1141 pp
= tcc_realloc(pp
, nb_alloc
* sizeof(void *));
1143 error("memory full");
1150 /* symbol allocator */
1151 static Sym
*__sym_malloc(void)
1153 Sym
*sym_pool
, *sym
, *last_sym
;
1156 sym_pool
= tcc_malloc(SYM_POOL_NB
* sizeof(Sym
));
1158 last_sym
= sym_free_first
;
1160 for(i
= 0; i
< SYM_POOL_NB
; i
++) {
1161 sym
->next
= last_sym
;
1165 sym_free_first
= last_sym
;
1169 static inline Sym
*sym_malloc(void)
1172 sym
= sym_free_first
;
1174 sym
= __sym_malloc();
1175 sym_free_first
= sym
->next
;
1179 static inline void sym_free(Sym
*sym
)
1181 sym
->next
= sym_free_first
;
1182 sym_free_first
= sym
;
1185 Section
*new_section(TCCState
*s1
, const char *name
, int sh_type
, int sh_flags
)
1189 sec
= tcc_mallocz(sizeof(Section
) + strlen(name
));
1190 strcpy(sec
->name
, name
);
1191 sec
->sh_type
= sh_type
;
1192 sec
->sh_flags
= sh_flags
;
1199 sec
->sh_addralign
= 4;
1202 sec
->sh_addralign
= 1;
1205 sec
->sh_addralign
= 32; /* default conservative alignment */
1209 /* only add section if not private */
1210 if (!(sh_flags
& SHF_PRIVATE
)) {
1211 sec
->sh_num
= s1
->nb_sections
;
1212 dynarray_add((void ***)&s1
->sections
, &s1
->nb_sections
, sec
);
1217 static void free_section(Section
*s
)
1223 /* realloc section and set its content to zero */
1224 static void section_realloc(Section
*sec
, unsigned long new_size
)
1227 unsigned char *data
;
1229 size
= sec
->data_allocated
;
1232 while (size
< new_size
)
1234 data
= tcc_realloc(sec
->data
, size
);
1236 error("memory full");
1237 memset(data
+ sec
->data_allocated
, 0, size
- sec
->data_allocated
);
1239 sec
->data_allocated
= size
;
1242 /* reserve at least 'size' bytes in section 'sec' from
1243 sec->data_offset. */
1244 static void *section_ptr_add(Section
*sec
, unsigned long size
)
1246 unsigned long offset
, offset1
;
1248 offset
= sec
->data_offset
;
1249 offset1
= offset
+ size
;
1250 if (offset1
> sec
->data_allocated
)
1251 section_realloc(sec
, offset1
);
1252 sec
->data_offset
= offset1
;
1253 return sec
->data
+ offset
;
1256 /* return a reference to a section, and create it if it does not
1258 Section
*find_section(TCCState
*s1
, const char *name
)
1262 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1263 sec
= s1
->sections
[i
];
1264 if (!strcmp(name
, sec
->name
))
1267 /* sections are created as PROGBITS */
1268 return new_section(s1
, name
, SHT_PROGBITS
, SHF_ALLOC
);
1271 #define SECTION_ABS ((void *)1)
1273 /* update sym->c so that it points to an external symbol in section
1274 'section' with value 'value' */
1275 static void put_extern_sym2(Sym
*sym
, Section
*section
,
1276 unsigned long value
, unsigned long size
,
1277 int can_add_underscore
)
1279 int sym_type
, sym_bind
, sh_num
, info
;
1284 if (section
== NULL
)
1286 else if (section
== SECTION_ABS
)
1289 sh_num
= section
->sh_num
;
1291 if ((sym
->type
.t
& VT_BTYPE
) == VT_FUNC
)
1292 sym_type
= STT_FUNC
;
1294 sym_type
= STT_OBJECT
;
1295 if (sym
->type
.t
& VT_STATIC
)
1296 sym_bind
= STB_LOCAL
;
1298 sym_bind
= STB_GLOBAL
;
1300 name
= get_tok_str(sym
->v
, NULL
);
1301 #ifdef CONFIG_TCC_BCHECK
1302 if (do_bounds_check
) {
1305 /* XXX: avoid doing that for statics ? */
1306 /* if bound checking is activated, we change some function
1307 names by adding the "__bound" prefix */
1310 /* XXX: we rely only on malloc hooks */
1323 strcpy(buf
, "__bound_");
1330 if (tcc_state
->leading_underscore
&& can_add_underscore
) {
1332 pstrcpy(buf1
+ 1, sizeof(buf1
) - 1, name
);
1335 info
= ELF32_ST_INFO(sym_bind
, sym_type
);
1336 sym
->c
= add_elf_sym(symtab_section
, value
, size
, info
, 0, sh_num
, name
);
1338 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
1339 esym
->st_value
= value
;
1340 esym
->st_size
= size
;
1341 esym
->st_shndx
= sh_num
;
1345 static void put_extern_sym(Sym
*sym
, Section
*section
,
1346 unsigned long value
, unsigned long size
)
1348 put_extern_sym2(sym
, section
, value
, size
, 1);
1351 /* add a new relocation entry to symbol 'sym' in section 's' */
1352 static void greloc(Section
*s
, Sym
*sym
, unsigned long offset
, int type
)
1355 put_extern_sym(sym
, NULL
, 0, 0);
1356 /* now we can add ELF relocation info */
1357 put_elf_reloc(symtab_section
, s
, offset
, type
, sym
->c
);
1360 static inline int isid(int c
)
1362 return (c
>= 'a' && c
<= 'z') ||
1363 (c
>= 'A' && c
<= 'Z') ||
1367 static inline int isnum(int c
)
1369 return c
>= '0' && c
<= '9';
1372 static inline int isoct(int c
)
1374 return c
>= '0' && c
<= '7';
1377 static inline int toup(int c
)
1379 if (c
>= 'a' && c
<= 'z')
1380 return c
- 'a' + 'A';
1385 static void strcat_vprintf(char *buf
, int buf_size
, const char *fmt
, va_list ap
)
1389 vsnprintf(buf
+ len
, buf_size
- len
, fmt
, ap
);
1392 static void strcat_printf(char *buf
, int buf_size
, const char *fmt
, ...)
1396 strcat_vprintf(buf
, buf_size
, fmt
, ap
);
1400 void error1(TCCState
*s1
, int is_warning
, const char *fmt
, va_list ap
)
1407 for(f
= s1
->include_stack
; f
< s1
->include_stack_ptr
; f
++)
1408 strcat_printf(buf
, sizeof(buf
), "In file included from %s:%d:\n",
1409 (*f
)->filename
, (*f
)->line_num
);
1410 if (file
->line_num
> 0) {
1411 strcat_printf(buf
, sizeof(buf
),
1412 "%s:%d: ", file
->filename
, file
->line_num
);
1414 strcat_printf(buf
, sizeof(buf
),
1415 "%s: ", file
->filename
);
1418 strcat_printf(buf
, sizeof(buf
),
1422 strcat_printf(buf
, sizeof(buf
), "warning: ");
1423 strcat_vprintf(buf
, sizeof(buf
), fmt
, ap
);
1425 if (!s1
->error_func
) {
1426 /* default case: stderr */
1427 fprintf(stderr
, "%s\n", buf
);
1429 s1
->error_func(s1
->error_opaque
, buf
);
1431 if (!is_warning
|| s1
->warn_error
)
1436 void tcc_set_error_func(TCCState
*s
, void *error_opaque
,
1437 void (*error_func
)(void *opaque
, const char *msg
))
1439 s
->error_opaque
= error_opaque
;
1440 s
->error_func
= error_func
;
1444 /* error without aborting current compilation */
1445 void error_noabort(const char *fmt
, ...)
1447 TCCState
*s1
= tcc_state
;
1451 error1(s1
, 0, fmt
, ap
);
1455 void error(const char *fmt
, ...)
1457 TCCState
*s1
= tcc_state
;
1461 error1(s1
, 0, fmt
, ap
);
1463 /* better than nothing: in some cases, we accept to handle errors */
1464 if (s1
->error_set_jmp_enabled
) {
1465 longjmp(s1
->error_jmp_buf
, 1);
1467 /* XXX: eliminate this someday */
1472 void expect(const char *msg
)
1474 error("%s expected", msg
);
1477 void warning(const char *fmt
, ...)
1479 TCCState
*s1
= tcc_state
;
1486 error1(s1
, 1, fmt
, ap
);
1493 error("'%c' expected", c
);
1497 static void test_lvalue(void)
1499 if (!(vtop
->r
& VT_LVAL
))
1503 /* allocate a new token */
1504 static TokenSym
*tok_alloc_new(TokenSym
**pts
, const char *str
, int len
)
1506 TokenSym
*ts
, **ptable
;
1509 if (tok_ident
>= SYM_FIRST_ANOM
)
1510 error("memory full");
1512 /* expand token table if needed */
1513 i
= tok_ident
- TOK_IDENT
;
1514 if ((i
% TOK_ALLOC_INCR
) == 0) {
1515 ptable
= tcc_realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
1517 error("memory full");
1518 table_ident
= ptable
;
1521 ts
= tcc_malloc(sizeof(TokenSym
) + len
);
1522 table_ident
[i
] = ts
;
1523 ts
->tok
= tok_ident
++;
1524 ts
->sym_define
= NULL
;
1525 ts
->sym_label
= NULL
;
1526 ts
->sym_struct
= NULL
;
1527 ts
->sym_identifier
= NULL
;
1529 ts
->hash_next
= NULL
;
1530 memcpy(ts
->str
, str
, len
);
1531 ts
->str
[len
] = '\0';
1536 #define TOK_HASH_INIT 1
1537 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1539 /* find a token and add it if not found */
1540 static TokenSym
*tok_alloc(const char *str
, int len
)
1542 TokenSym
*ts
, **pts
;
1548 h
= TOK_HASH_FUNC(h
, ((unsigned char *)str
)[i
]);
1549 h
&= (TOK_HASH_SIZE
- 1);
1551 pts
= &hash_ident
[h
];
1556 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
1558 pts
= &(ts
->hash_next
);
1560 return tok_alloc_new(pts
, str
, len
);
1563 /* CString handling */
1565 static void cstr_realloc(CString
*cstr
, int new_size
)
1570 size
= cstr
->size_allocated
;
1572 size
= 8; /* no need to allocate a too small first string */
1573 while (size
< new_size
)
1575 data
= tcc_realloc(cstr
->data_allocated
, size
);
1577 error("memory full");
1578 cstr
->data_allocated
= data
;
1579 cstr
->size_allocated
= size
;
1584 static inline void cstr_ccat(CString
*cstr
, int ch
)
1587 size
= cstr
->size
+ 1;
1588 if (size
> cstr
->size_allocated
)
1589 cstr_realloc(cstr
, size
);
1590 ((unsigned char *)cstr
->data
)[size
- 1] = ch
;
1594 static void cstr_cat(CString
*cstr
, const char *str
)
1606 /* add a wide char */
1607 static void cstr_wccat(CString
*cstr
, int ch
)
1610 size
= cstr
->size
+ sizeof(nwchar_t
);
1611 if (size
> cstr
->size_allocated
)
1612 cstr_realloc(cstr
, size
);
1613 *(nwchar_t
*)(((unsigned char *)cstr
->data
) + size
- sizeof(nwchar_t
)) = ch
;
1617 static void cstr_new(CString
*cstr
)
1619 memset(cstr
, 0, sizeof(CString
));
1622 /* free string and reset it to NULL */
1623 static void cstr_free(CString
*cstr
)
1625 tcc_free(cstr
->data_allocated
);
1629 #define cstr_reset(cstr) cstr_free(cstr)
1631 /* XXX: unicode ? */
1632 static void add_char(CString
*cstr
, int c
)
1634 if (c
== '\'' || c
== '\"' || c
== '\\') {
1635 /* XXX: could be more precise if char or string */
1636 cstr_ccat(cstr
, '\\');
1638 if (c
>= 32 && c
<= 126) {
1641 cstr_ccat(cstr
, '\\');
1643 cstr_ccat(cstr
, 'n');
1645 cstr_ccat(cstr
, '0' + ((c
>> 6) & 7));
1646 cstr_ccat(cstr
, '0' + ((c
>> 3) & 7));
1647 cstr_ccat(cstr
, '0' + (c
& 7));
1652 /* XXX: buffer overflow */
1653 /* XXX: float tokens */
1654 char *get_tok_str(int v
, CValue
*cv
)
1656 static char buf
[STRING_MAX_SIZE
+ 1];
1657 static CString cstr_buf
;
1663 /* NOTE: to go faster, we give a fixed buffer for small strings */
1664 cstr_reset(&cstr_buf
);
1665 cstr_buf
.data
= buf
;
1666 cstr_buf
.size_allocated
= sizeof(buf
);
1672 /* XXX: not quite exact, but only useful for testing */
1673 sprintf(p
, "%u", cv
->ui
);
1677 /* XXX: not quite exact, but only useful for testing */
1678 sprintf(p
, "%Lu", cv
->ull
);
1682 cstr_ccat(&cstr_buf
, '\'');
1683 add_char(&cstr_buf
, cv
->i
);
1684 cstr_ccat(&cstr_buf
, '\'');
1685 cstr_ccat(&cstr_buf
, '\0');
1689 len
= cstr
->size
- 1;
1691 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1692 cstr_ccat(&cstr_buf
, '\0');
1697 cstr_ccat(&cstr_buf
, '\"');
1699 len
= cstr
->size
- 1;
1701 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1703 len
= (cstr
->size
/ sizeof(nwchar_t
)) - 1;
1705 add_char(&cstr_buf
, ((nwchar_t
*)cstr
->data
)[i
]);
1707 cstr_ccat(&cstr_buf
, '\"');
1708 cstr_ccat(&cstr_buf
, '\0');
1717 return strcpy(p
, "...");
1719 return strcpy(p
, "<<=");
1721 return strcpy(p
, ">>=");
1723 if (v
< TOK_IDENT
) {
1724 /* search in two bytes table */
1738 } else if (v
< tok_ident
) {
1739 return table_ident
[v
- TOK_IDENT
]->str
;
1740 } else if (v
>= SYM_FIRST_ANOM
) {
1741 /* special name for anonymous symbol */
1742 sprintf(p
, "L.%u", v
- SYM_FIRST_ANOM
);
1744 /* should never happen */
1749 return cstr_buf
.data
;
1752 /* push, without hashing */
1753 static Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
1767 /* find a symbol and return its associated structure. 's' is the top
1768 of the symbol stack */
1769 static Sym
*sym_find2(Sym
*s
, int v
)
1779 /* structure lookup */
1780 static inline Sym
*struct_find(int v
)
1783 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1785 return table_ident
[v
]->sym_struct
;
1788 /* find an identifier */
1789 static inline Sym
*sym_find(int v
)
1792 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1794 return table_ident
[v
]->sym_identifier
;
1797 /* push a given symbol on the symbol stack */
1798 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
)
1807 s
= sym_push2(ps
, v
, type
->t
, c
);
1808 s
->type
.ref
= type
->ref
;
1810 /* don't record fields or anonymous symbols */
1812 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1813 /* record symbol in token array */
1814 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1816 ps
= &ts
->sym_struct
;
1818 ps
= &ts
->sym_identifier
;
1825 /* push a global identifier */
1826 static Sym
*global_identifier_push(int v
, int t
, int c
)
1829 s
= sym_push2(&global_stack
, v
, t
, c
);
1830 /* don't record anonymous symbol */
1831 if (v
< SYM_FIRST_ANOM
) {
1832 ps
= &table_ident
[v
- TOK_IDENT
]->sym_identifier
;
1833 /* modify the top most local identifier, so that
1834 sym_identifier will point to 's' when popped */
1836 ps
= &(*ps
)->prev_tok
;
1843 /* pop symbols until top reaches 'b' */
1844 static void sym_pop(Sym
**ptop
, Sym
*b
)
1854 /* remove symbol in token array */
1856 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1857 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1859 ps
= &ts
->sym_struct
;
1861 ps
= &ts
->sym_identifier
;
1872 BufferedFile
*tcc_open(TCCState
*s1
, const char *filename
)
1877 fd
= open(filename
, O_RDONLY
| O_BINARY
);
1880 bf
= tcc_malloc(sizeof(BufferedFile
));
1886 bf
->buf_ptr
= bf
->buffer
;
1887 bf
->buf_end
= bf
->buffer
;
1888 bf
->buffer
[0] = CH_EOB
; /* put eob symbol */
1889 pstrcpy(bf
->filename
, sizeof(bf
->filename
), filename
);
1890 normalize_slashes(bf
->filename
);
1892 bf
->ifndef_macro
= 0;
1893 bf
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
1894 // printf("opening '%s'\n", filename);
1898 void tcc_close(BufferedFile
*bf
)
1900 total_lines
+= bf
->line_num
;
1905 /* fill input buffer and peek next char */
1906 static int tcc_peekc_slow(BufferedFile
*bf
)
1909 /* only tries to read if really end of buffer */
1910 if (bf
->buf_ptr
>= bf
->buf_end
) {
1912 #if defined(PARSE_DEBUG)
1917 len
= read(bf
->fd
, bf
->buffer
, len
);
1924 bf
->buf_ptr
= bf
->buffer
;
1925 bf
->buf_end
= bf
->buffer
+ len
;
1926 *bf
->buf_end
= CH_EOB
;
1928 if (bf
->buf_ptr
< bf
->buf_end
) {
1929 return bf
->buf_ptr
[0];
1931 bf
->buf_ptr
= bf
->buf_end
;
1936 /* return the current character, handling end of block if necessary
1938 static int handle_eob(void)
1940 return tcc_peekc_slow(file
);
1943 /* read next char from current input file and handle end of input buffer */
1944 static inline void inp(void)
1946 ch
= *(++(file
->buf_ptr
));
1947 /* end of buffer/file handling */
1952 /* handle '\[\r]\n' */
1953 static void handle_stray(void)
1955 while (ch
== '\\') {
1960 } else if (ch
== '\r') {
1968 error("stray '\\' in program");
1973 /* skip the stray and handle the \\n case. Output an error if
1974 incorrect char after the stray */
1975 static int handle_stray1(uint8_t *p
)
1979 if (p
>= file
->buf_end
) {
1996 /* handle just the EOB case, but not stray */
1997 #define PEEKC_EOB(c, p)\
2008 /* handle the complicated stray case */
2009 #define PEEKC(c, p)\
2014 c = handle_stray1(p);\
2019 /* input with '\[\r]\n' handling. Note that this function cannot
2020 handle other characters after '\', so you cannot call it inside
2021 strings or comments */
2022 static void minp(void)
2030 /* single line C++ comments */
2031 static uint8_t *parse_line_comment(uint8_t *p
)
2039 if (c
== '\n' || c
== CH_EOF
) {
2041 } else if (c
== '\\') {
2050 } else if (c
== '\r') {
2068 static uint8_t *parse_comment(uint8_t *p
)
2074 /* fast skip loop */
2077 if (c
== '\n' || c
== '*' || c
== '\\')
2081 if (c
== '\n' || c
== '*' || c
== '\\')
2085 /* now we can handle all the cases */
2089 } else if (c
== '*') {
2095 } else if (c
== '/') {
2096 goto end_of_comment
;
2097 } else if (c
== '\\') {
2102 /* skip '\[\r]\n', otherwise just skip the stray */
2108 } else if (c
== '\r') {
2125 /* stray, eob or eof */
2130 error("unexpected end of file in comment");
2131 } else if (c
== '\\') {
2143 /* space exlcuding newline */
2144 static inline int is_space(int ch
)
2146 return ch
== ' ' || ch
== '\t' || ch
== '\v' || ch
== '\f' || ch
== '\r';
2149 static inline void skip_spaces(void)
2151 while (is_space(ch
))
2155 /* parse a string without interpreting escapes */
2156 static uint8_t *parse_pp_string(uint8_t *p
,
2157 int sep
, CString
*str
)
2165 } else if (c
== '\\') {
2170 unterminated_string
:
2171 /* XXX: indicate line number of start of string */
2172 error("missing terminating %c character", sep
);
2173 } else if (c
== '\\') {
2174 /* escape : just skip \[\r]\n */
2179 } else if (c
== '\r') {
2182 expect("'\n' after '\r'");
2185 } else if (c
== CH_EOF
) {
2186 goto unterminated_string
;
2189 cstr_ccat(str
, '\\');
2195 } else if (c
== '\n') {
2198 } else if (c
== '\r') {
2202 cstr_ccat(str
, '\r');
2218 /* skip block of text until #else, #elif or #endif. skip also pairs of
2220 void preprocess_skip(void)
2222 int a
, start_of_line
, c
;
2249 } else if (c
== '\\') {
2250 /* XXX: incorrect: should not give an error */
2251 ch
= file
->buf_ptr
[0];
2259 p
= parse_pp_string(p
, c
, NULL
);
2268 p
= parse_comment(p
);
2269 } else if (ch
== '/') {
2270 p
= parse_line_comment(p
);
2276 if (start_of_line
) {
2281 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
2283 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
2285 else if (tok
== TOK_ENDIF
)
2299 /* ParseState handling */
2301 /* XXX: currently, no include file info is stored. Thus, we cannot display
2302 accurate messages if the function or data definition spans multiple
2305 /* save current parse state in 's' */
2306 void save_parse_state(ParseState
*s
)
2308 s
->line_num
= file
->line_num
;
2309 s
->macro_ptr
= macro_ptr
;
2314 /* restore parse state from 's' */
2315 void restore_parse_state(ParseState
*s
)
2317 file
->line_num
= s
->line_num
;
2318 macro_ptr
= s
->macro_ptr
;
2323 /* return the number of additional 'ints' necessary to store the
2325 static inline int tok_ext_size(int t
)
2339 error("unsupported token");
2346 return LDOUBLE_SIZE
/ 4;
2352 /* token string handling */
2354 static inline void tok_str_new(TokenString
*s
)
2358 s
->allocated_len
= 0;
2359 s
->last_line_num
= -1;
2362 static void tok_str_free(int *str
)
2367 static int *tok_str_realloc(TokenString
*s
)
2371 if (s
->allocated_len
== 0) {
2374 len
= s
->allocated_len
* 2;
2376 str
= tcc_realloc(s
->str
, len
* sizeof(int));
2378 error("memory full");
2379 s
->allocated_len
= len
;
2384 static void tok_str_add(TokenString
*s
, int t
)
2390 if (len
>= s
->allocated_len
)
2391 str
= tok_str_realloc(s
);
2396 static void tok_str_add2(TokenString
*s
, int t
, CValue
*cv
)
2403 /* allocate space for worst case */
2404 if (len
+ TOK_MAX_SIZE
> s
->allocated_len
)
2405 str
= tok_str_realloc(s
);
2414 str
[len
++] = cv
->tab
[0];
2423 nb_words
= (sizeof(CString
) + cv
->cstr
->size
+ 3) >> 2;
2424 while ((len
+ nb_words
) > s
->allocated_len
)
2425 str
= tok_str_realloc(s
);
2426 cstr
= (CString
*)(str
+ len
);
2428 cstr
->size
= cv
->cstr
->size
;
2429 cstr
->data_allocated
= NULL
;
2430 cstr
->size_allocated
= cstr
->size
;
2431 memcpy((char *)cstr
+ sizeof(CString
),
2432 cv
->cstr
->data
, cstr
->size
);
2439 #if LDOUBLE_SIZE == 8
2442 str
[len
++] = cv
->tab
[0];
2443 str
[len
++] = cv
->tab
[1];
2445 #if LDOUBLE_SIZE == 12
2447 str
[len
++] = cv
->tab
[0];
2448 str
[len
++] = cv
->tab
[1];
2449 str
[len
++] = cv
->tab
[2];
2450 #elif LDOUBLE_SIZE != 8
2451 #error add long double size support
2460 /* add the current parse token in token string 's' */
2461 static void tok_str_add_tok(TokenString
*s
)
2465 /* save line number info */
2466 if (file
->line_num
!= s
->last_line_num
) {
2467 s
->last_line_num
= file
->line_num
;
2468 cval
.i
= s
->last_line_num
;
2469 tok_str_add2(s
, TOK_LINENUM
, &cval
);
2471 tok_str_add2(s
, tok
, &tokc
);
2474 #if LDOUBLE_SIZE == 12
2475 #define LDOUBLE_GET(p, cv) \
2479 #elif LDOUBLE_SIZE == 8
2480 #define LDOUBLE_GET(p, cv) \
2484 #error add long double size support
2488 /* get a token from an integer array and increment pointer
2489 accordingly. we code it as a macro to avoid pointer aliasing. */
2490 #define TOK_GET(t, p, cv) \
2505 cv.cstr = (CString *)p; \
2506 cv.cstr->data = (char *)p + sizeof(CString);\
2507 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2516 case TOK_CLDOUBLE: \
2517 LDOUBLE_GET(p, cv); \
2518 p += LDOUBLE_SIZE / 4; \
2525 /* defines handling */
2526 static inline void define_push(int v
, int macro_type
, int *str
, Sym
*first_arg
)
2530 s
= sym_push2(&define_stack
, v
, macro_type
, (int)str
);
2531 s
->next
= first_arg
;
2532 table_ident
[v
- TOK_IDENT
]->sym_define
= s
;
2535 /* undefined a define symbol. Its name is just set to zero */
2536 static void define_undef(Sym
*s
)
2540 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2541 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2545 static inline Sym
*define_find(int v
)
2548 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2550 return table_ident
[v
]->sym_define
;
2553 /* free define stack until top reaches 'b' */
2554 static void free_defines(Sym
*b
)
2562 /* do not free args or predefined defines */
2564 tok_str_free((int *)top
->c
);
2566 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2567 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2575 static Sym
*label_find(int v
)
2578 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2580 return table_ident
[v
]->sym_label
;
2583 static Sym
*label_push(Sym
**ptop
, int v
, int flags
)
2586 s
= sym_push2(ptop
, v
, 0, 0);
2588 ps
= &table_ident
[v
- TOK_IDENT
]->sym_label
;
2589 if (ptop
== &global_label_stack
) {
2590 /* modify the top most local identifier, so that
2591 sym_identifier will point to 's' when popped */
2593 ps
= &(*ps
)->prev_tok
;
2600 /* pop labels until element last is reached. Look if any labels are
2601 undefined. Define symbols if '&&label' was used. */
2602 static void label_pop(Sym
**ptop
, Sym
*slast
)
2605 for(s
= *ptop
; s
!= slast
; s
= s1
) {
2607 if (s
->r
== LABEL_DECLARED
) {
2608 warning("label '%s' declared but not used", get_tok_str(s
->v
, NULL
));
2609 } else if (s
->r
== LABEL_FORWARD
) {
2610 error("label '%s' used but not defined",
2611 get_tok_str(s
->v
, NULL
));
2614 /* define corresponding symbol. A size of
2616 put_extern_sym(s
, cur_text_section
, (long)s
->next
, 1);
2620 table_ident
[s
->v
- TOK_IDENT
]->sym_label
= s
->prev_tok
;
2626 /* eval an expression for #if/#elif */
2627 static int expr_preprocess(void)
2633 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2634 next(); /* do macro subst */
2635 if (tok
== TOK_DEFINED
) {
2640 c
= define_find(tok
) != 0;
2645 } else if (tok
>= TOK_IDENT
) {
2646 /* if undefined macro */
2650 tok_str_add_tok(&str
);
2652 tok_str_add(&str
, -1); /* simulate end of file */
2653 tok_str_add(&str
, 0);
2654 /* now evaluate C constant expression */
2655 macro_ptr
= str
.str
;
2659 tok_str_free(str
.str
);
2663 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2664 static void tok_print(int *str
)
2670 TOK_GET(t
, str
, cval
);
2673 printf(" %s", get_tok_str(t
, &cval
));
2679 /* parse after #define */
2680 static void parse_define(void)
2682 Sym
*s
, *first
, **ps
;
2683 int v
, t
, varg
, is_vaargs
, c
;
2688 error("invalid macro name '%s'", get_tok_str(tok
, &tokc
));
2689 /* XXX: should check if same macro (ANSI) */
2692 /* '(' must be just after macro definition for MACRO_FUNC */
2693 c
= file
->buf_ptr
[0];
2695 c
= handle_stray1(file
->buf_ptr
);
2700 while (tok
!= ')') {
2704 if (varg
== TOK_DOTS
) {
2705 varg
= TOK___VA_ARGS__
;
2707 } else if (tok
== TOK_DOTS
&& gnu_ext
) {
2711 if (varg
< TOK_IDENT
)
2712 error("badly punctuated parameter list");
2713 s
= sym_push2(&define_stack
, varg
| SYM_FIELD
, is_vaargs
, 0);
2724 /* EOF testing necessary for '-D' handling */
2725 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2726 tok_str_add2(&str
, tok
, &tokc
);
2729 tok_str_add(&str
, 0);
2731 printf("define %s %d: ", get_tok_str(v
, NULL
), t
);
2734 define_push(v
, t
, str
.str
, first
);
2737 static inline int hash_cached_include(int type
, const char *filename
)
2739 const unsigned char *s
;
2743 h
= TOK_HASH_FUNC(h
, type
);
2746 h
= TOK_HASH_FUNC(h
, *s
);
2749 h
&= (CACHED_INCLUDES_HASH_SIZE
- 1);
2753 /* XXX: use a token or a hash table to accelerate matching ? */
2754 static CachedInclude
*search_cached_include(TCCState
*s1
,
2755 int type
, const char *filename
)
2759 h
= hash_cached_include(type
, filename
);
2760 i
= s1
->cached_includes_hash
[h
];
2764 e
= s1
->cached_includes
[i
- 1];
2765 if (e
->type
== type
&& !strcmp(e
->filename
, filename
))
2772 static inline void add_cached_include(TCCState
*s1
, int type
,
2773 const char *filename
, int ifndef_macro
)
2778 if (search_cached_include(s1
, type
, filename
))
2781 printf("adding cached '%s' %s\n", filename
, get_tok_str(ifndef_macro
, NULL
));
2783 e
= tcc_malloc(sizeof(CachedInclude
) + strlen(filename
));
2787 strcpy(e
->filename
, filename
);
2788 e
->ifndef_macro
= ifndef_macro
;
2789 dynarray_add((void ***)&s1
->cached_includes
, &s1
->nb_cached_includes
, e
);
2790 /* add in hash table */
2791 h
= hash_cached_include(type
, filename
);
2792 e
->hash_next
= s1
->cached_includes_hash
[h
];
2793 s1
->cached_includes_hash
[h
] = s1
->nb_cached_includes
;
2796 static void pragma_parse(TCCState
*s1
)
2801 if (tok
== TOK_pack
) {
2804 #pragma pack(1) // set
2805 #pragma pack() // reset to default
2806 #pragma pack(push,1) // push & set
2807 #pragma pack(pop) // restore previous
2811 if (tok
== TOK_ASM_pop
) {
2813 if (s1
->pack_stack_ptr
<= s1
->pack_stack
) {
2815 error("out of pack stack");
2817 s1
->pack_stack_ptr
--;
2821 if (tok
== TOK_ASM_push
) {
2823 if (s1
->pack_stack_ptr
>= s1
->pack_stack
+ PACK_STACK_SIZE
- 1)
2825 s1
->pack_stack_ptr
++;
2828 if (tok
!= TOK_CINT
) {
2830 error("invalid pack pragma");
2833 if (val
< 1 || val
> 16 || (val
& (val
- 1)) != 0)
2837 *s1
->pack_stack_ptr
= val
;
2843 /* is_bof is true if first non space token at beginning of file */
2844 static void preprocess(int is_bof
)
2846 TCCState
*s1
= tcc_state
;
2847 int size
, i
, c
, n
, saved_parse_flags
;
2848 char buf
[1024], *q
, *p
;
2854 saved_parse_flags
= parse_flags
;
2855 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
|
2856 PARSE_FLAG_LINEFEED
;
2866 s
= define_find(tok
);
2867 /* undefine symbol by putting an invalid name */
2872 case TOK_INCLUDE_NEXT
:
2873 ch
= file
->buf_ptr
[0];
2874 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2879 } else if (ch
== '\"') {
2882 /* XXX: better stray handling */
2885 while (ch
!= c
&& ch
!= '\n' && ch
!= CH_EOF
) {
2886 if ((q
- buf
) < sizeof(buf
) - 1)
2893 /* eat all spaces and comments after include */
2894 /* XXX: slightly incorrect */
2895 while (ch1
!= '\n' && ch1
!= CH_EOF
)
2899 /* computed #include : either we have only strings or
2900 we have anything enclosed in '<>' */
2903 if (tok
== TOK_STR
) {
2904 while (tok
!= TOK_LINEFEED
) {
2905 if (tok
!= TOK_STR
) {
2907 error("'#include' expects \"FILENAME\" or <FILENAME>");
2909 pstrcat(buf
, sizeof(buf
), (char *)tokc
.cstr
->data
);
2915 while (tok
!= TOK_LINEFEED
) {
2916 pstrcat(buf
, sizeof(buf
), get_tok_str(tok
, &tokc
));
2920 /* check syntax and remove '<>' */
2921 if (len
< 2 || buf
[0] != '<' || buf
[len
- 1] != '>')
2922 goto include_syntax
;
2923 memmove(buf
, buf
+ 1, len
- 2);
2924 buf
[len
- 2] = '\0';
2929 e
= search_cached_include(s1
, c
, buf
);
2930 if (e
&& define_find(e
->ifndef_macro
)) {
2931 /* no need to parse the include because the 'ifndef macro'
2934 printf("%s: skipping %s\n", file
->filename
, buf
);
2938 /* first search in current dir if "header.h" */
2940 p
= strrchr(file
->filename
, '/');
2942 size
= p
+ 1 - file
->filename
;
2943 if (size
> sizeof(buf1
) - 1)
2944 size
= sizeof(buf1
) - 1;
2945 memcpy(buf1
, file
->filename
, size
);
2947 pstrcat(buf1
, sizeof(buf1
), buf
);
2948 f
= tcc_open(s1
, buf1
);
2950 if (tok
== TOK_INCLUDE_NEXT
)
2956 if (s1
->include_stack_ptr
>= s1
->include_stack
+ INCLUDE_STACK_SIZE
)
2957 error("#include recursion too deep");
2958 /* now search in all the include paths */
2959 n
= s1
->nb_include_paths
+ s1
->nb_sysinclude_paths
;
2960 for(i
= 0; i
< n
; i
++) {
2962 if (i
< s1
->nb_include_paths
)
2963 path
= s1
->include_paths
[i
];
2965 path
= s1
->sysinclude_paths
[i
- s1
->nb_include_paths
];
2966 pstrcpy(buf1
, sizeof(buf1
), path
);
2967 pstrcat(buf1
, sizeof(buf1
), "/");
2968 pstrcat(buf1
, sizeof(buf1
), buf
);
2969 f
= tcc_open(s1
, buf1
);
2971 if (tok
== TOK_INCLUDE_NEXT
)
2977 error("include file '%s' not found", buf
);
2981 printf("%s: including %s\n", file
->filename
, buf1
);
2984 pstrcpy(f
->inc_filename
, sizeof(f
->inc_filename
), buf
);
2985 /* push current file in stack */
2986 /* XXX: fix current line init */
2987 *s1
->include_stack_ptr
++ = file
;
2989 /* add include file debug info */
2991 put_stabs(file
->filename
, N_BINCL
, 0, 0, 0);
2993 tok_flags
|= TOK_FLAG_BOF
| TOK_FLAG_BOL
;
2994 ch
= file
->buf_ptr
[0];
3002 c
= expr_preprocess();
3008 if (tok
< TOK_IDENT
)
3009 error("invalid argument for '#if%sdef'", c
? "n" : "");
3013 printf("#ifndef %s\n", get_tok_str(tok
, NULL
));
3015 file
->ifndef_macro
= tok
;
3018 c
= (define_find(tok
) != 0) ^ c
;
3020 if (s1
->ifdef_stack_ptr
>= s1
->ifdef_stack
+ IFDEF_STACK_SIZE
)
3021 error("memory full");
3022 *s1
->ifdef_stack_ptr
++ = c
;
3025 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
3026 error("#else without matching #if");
3027 if (s1
->ifdef_stack_ptr
[-1] & 2)
3028 error("#else after #else");
3029 c
= (s1
->ifdef_stack_ptr
[-1] ^= 3);
3032 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
3033 error("#elif without matching #if");
3034 c
= s1
->ifdef_stack_ptr
[-1];
3036 error("#elif after #else");
3037 /* last #if/#elif expression was true: we skip */
3040 c
= expr_preprocess();
3041 s1
->ifdef_stack_ptr
[-1] = c
;
3051 if (s1
->ifdef_stack_ptr
<= file
->ifdef_stack_ptr
)
3052 error("#endif without matching #if");
3053 s1
->ifdef_stack_ptr
--;
3054 /* '#ifndef macro' was at the start of file. Now we check if
3055 an '#endif' is exactly at the end of file */
3056 if (file
->ifndef_macro
&&
3057 s1
->ifdef_stack_ptr
== file
->ifdef_stack_ptr
) {
3058 file
->ifndef_macro_saved
= file
->ifndef_macro
;
3059 /* need to set to zero to avoid false matches if another
3060 #ifndef at middle of file */
3061 file
->ifndef_macro
= 0;
3062 while (tok
!= TOK_LINEFEED
)
3064 tok_flags
|= TOK_FLAG_ENDIF
;
3070 if (tok
!= TOK_CINT
)
3072 file
->line_num
= tokc
.i
- 1; /* the line number will be incremented after */
3074 if (tok
!= TOK_LINEFEED
) {
3077 pstrcpy(file
->filename
, sizeof(file
->filename
),
3078 (char *)tokc
.cstr
->data
);
3084 ch
= file
->buf_ptr
[0];
3087 while (ch
!= '\n' && ch
!= CH_EOF
) {
3088 if ((q
- buf
) < sizeof(buf
) - 1)
3094 error("#error %s", buf
);
3096 warning("#warning %s", buf
);
3102 if (tok
== TOK_LINEFEED
|| tok
== '!' || tok
== TOK_CINT
) {
3103 /* '!' is ignored to allow C scripts. numbers are ignored
3104 to emulate cpp behaviour */
3106 if (!(saved_parse_flags
& PARSE_FLAG_ASM_COMMENTS
))
3107 error("invalid preprocessing directive #%s", get_tok_str(tok
, &tokc
));
3111 /* ignore other preprocess commands or #! for C scripts */
3112 while (tok
!= TOK_LINEFEED
)
3115 parse_flags
= saved_parse_flags
;
3118 /* evaluate escape codes in a string. */
3119 static void parse_escape_string(CString
*outstr
, const uint8_t *buf
, int is_long
)
3134 case '0': case '1': case '2': case '3':
3135 case '4': case '5': case '6': case '7':
3136 /* at most three octal digits */
3141 n
= n
* 8 + c
- '0';
3145 n
= n
* 8 + c
- '0';
3150 goto add_char_nonext
;
3158 if (c
>= 'a' && c
<= 'f')
3160 else if (c
>= 'A' && c
<= 'F')
3170 goto add_char_nonext
;
3194 goto invalid_escape
;
3204 if (c
>= '!' && c
<= '~')
3205 warning("unknown escape sequence: \'\\%c\'", c
);
3207 warning("unknown escape sequence: \'\\x%x\'", c
);
3214 cstr_ccat(outstr
, c
);
3216 cstr_wccat(outstr
, c
);
3218 /* add a trailing '\0' */
3220 cstr_ccat(outstr
, '\0');
3222 cstr_wccat(outstr
, '\0');
3225 /* we use 64 bit numbers */
3228 /* bn = (bn << shift) | or_val */
3229 void bn_lshift(unsigned int *bn
, int shift
, int or_val
)
3233 for(i
=0;i
<BN_SIZE
;i
++) {
3235 bn
[i
] = (v
<< shift
) | or_val
;
3236 or_val
= v
>> (32 - shift
);
3240 void bn_zero(unsigned int *bn
)
3243 for(i
=0;i
<BN_SIZE
;i
++) {
3248 /* parse number in null terminated string 'p' and return it in the
3250 void parse_number(const char *p
)
3252 int b
, t
, shift
, frac_bits
, s
, exp_val
, ch
;
3254 unsigned int bn
[BN_SIZE
];
3265 goto float_frac_parse
;
3266 } else if (t
== '0') {
3267 if (ch
== 'x' || ch
== 'X') {
3271 } else if (tcc_ext
&& (ch
== 'b' || ch
== 'B')) {
3277 /* parse all digits. cannot check octal numbers at this stage
3278 because of floating point constants */
3280 if (ch
>= 'a' && ch
<= 'f')
3282 else if (ch
>= 'A' && ch
<= 'F')
3290 if (q
>= token_buf
+ STRING_MAX_SIZE
) {
3292 error("number too long");
3298 ((ch
== 'e' || ch
== 'E') && b
== 10) ||
3299 ((ch
== 'p' || ch
== 'P') && (b
== 16 || b
== 2))) {
3301 /* NOTE: strtox should support that for hexa numbers, but
3302 non ISOC99 libcs do not support it, so we prefer to do
3304 /* hexadecimal or binary floats */
3305 /* XXX: handle overflows */
3317 } else if (t
>= 'a') {
3319 } else if (t
>= 'A') {
3324 bn_lshift(bn
, shift
, t
);
3331 if (t
>= 'a' && t
<= 'f') {
3333 } else if (t
>= 'A' && t
<= 'F') {
3335 } else if (t
>= '0' && t
<= '9') {
3341 error("invalid digit");
3342 bn_lshift(bn
, shift
, t
);
3347 if (ch
!= 'p' && ch
!= 'P')
3354 } else if (ch
== '-') {
3358 if (ch
< '0' || ch
> '9')
3359 expect("exponent digits");
3360 while (ch
>= '0' && ch
<= '9') {
3361 exp_val
= exp_val
* 10 + ch
- '0';
3364 exp_val
= exp_val
* s
;
3366 /* now we can generate the number */
3367 /* XXX: should patch directly float number */
3368 d
= (double)bn
[1] * 4294967296.0 + (double)bn
[0];
3369 d
= ldexp(d
, exp_val
- frac_bits
);
3374 /* float : should handle overflow */
3376 } else if (t
== 'L') {
3379 /* XXX: not large enough */
3380 tokc
.ld
= (long double)d
;
3386 /* decimal floats */
3388 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3393 while (ch
>= '0' && ch
<= '9') {
3394 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3400 if (ch
== 'e' || ch
== 'E') {
3401 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3405 if (ch
== '-' || ch
== '+') {
3406 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3411 if (ch
< '0' || ch
> '9')
3412 expect("exponent digits");
3413 while (ch
>= '0' && ch
<= '9') {
3414 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3426 tokc
.f
= strtof(token_buf
, NULL
);
3427 } else if (t
== 'L') {
3430 tokc
.ld
= strtold(token_buf
, NULL
);
3433 tokc
.d
= strtod(token_buf
, NULL
);
3437 unsigned long long n
, n1
;
3440 /* integer number */
3443 if (b
== 10 && *q
== '0') {
3450 /* no need for checks except for base 10 / 8 errors */
3453 } else if (t
>= 'a') {
3455 } else if (t
>= 'A') {
3460 error("invalid digit");
3464 /* detect overflow */
3465 /* XXX: this test is not reliable */
3467 error("integer constant overflow");
3470 /* XXX: not exactly ANSI compliant */
3471 if ((n
& 0xffffffff00000000LL
) != 0) {
3476 } else if (n
> 0x7fffffff) {
3487 error("three 'l's in integer constant");
3490 if (tok
== TOK_CINT
)
3492 else if (tok
== TOK_CUINT
)
3496 } else if (t
== 'U') {
3498 error("two 'u's in integer constant");
3500 if (tok
== TOK_CINT
)
3502 else if (tok
== TOK_CLLONG
)
3509 if (tok
== TOK_CINT
|| tok
== TOK_CUINT
)
3517 #define PARSE2(c1, tok1, c2, tok2) \
3528 /* return next token without macro substitution */
3529 static inline void next_nomacro1(void)
3549 /* first look if it is in fact an end of buffer */
3550 if (p
>= file
->buf_end
) {
3554 if (p
>= file
->buf_end
)
3567 TCCState
*s1
= tcc_state
;
3568 if ((parse_flags
& PARSE_FLAG_LINEFEED
)
3569 && !(tok_flags
& TOK_FLAG_EOF
)) {
3570 tok_flags
|= TOK_FLAG_EOF
;
3572 goto keep_tok_flags
;
3573 } else if (s1
->include_stack_ptr
== s1
->include_stack
||
3574 !(parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3575 /* no include left : end of file. */
3578 tok_flags
&= ~TOK_FLAG_EOF
;
3579 /* pop include file */
3581 /* test if previous '#endif' was after a #ifdef at
3583 if (tok_flags
& TOK_FLAG_ENDIF
) {
3585 printf("#endif %s\n", get_tok_str(file
->ifndef_macro_saved
, NULL
));
3587 add_cached_include(s1
, file
->inc_type
, file
->inc_filename
,
3588 file
->ifndef_macro_saved
);
3591 /* add end of include file debug info */
3593 put_stabd(N_EINCL
, 0, 0);
3595 /* pop include stack */
3597 s1
->include_stack_ptr
--;
3598 file
= *s1
->include_stack_ptr
;
3607 tok_flags
|= TOK_FLAG_BOL
;
3609 if (0 == (parse_flags
& PARSE_FLAG_LINEFEED
))
3612 goto keep_tok_flags
;
3617 if ((tok_flags
& TOK_FLAG_BOL
) &&
3618 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3620 preprocess(tok_flags
& TOK_FLAG_BOF
);
3626 tok
= TOK_TWOSHARPS
;
3628 if (parse_flags
& PARSE_FLAG_ASM_COMMENTS
) {
3629 p
= parse_line_comment(p
- 1);
3638 case 'a': case 'b': case 'c': case 'd':
3639 case 'e': case 'f': case 'g': case 'h':
3640 case 'i': case 'j': case 'k': case 'l':
3641 case 'm': case 'n': case 'o': case 'p':
3642 case 'q': case 'r': case 's': case 't':
3643 case 'u': case 'v': case 'w': case 'x':
3645 case 'A': case 'B': case 'C': case 'D':
3646 case 'E': case 'F': case 'G': case 'H':
3647 case 'I': case 'J': case 'K':
3648 case 'M': case 'N': case 'O': case 'P':
3649 case 'Q': case 'R': case 'S': case 'T':
3650 case 'U': case 'V': case 'W': case 'X':
3656 h
= TOK_HASH_FUNC(h
, c
);
3660 if (!isidnum_table
[c
])
3662 h
= TOK_HASH_FUNC(h
, c
);
3669 /* fast case : no stray found, so we have the full token
3670 and we have already hashed it */
3672 h
&= (TOK_HASH_SIZE
- 1);
3673 pts
= &hash_ident
[h
];
3678 if (ts
->len
== len
&& !memcmp(ts
->str
, p1
, len
))
3680 pts
= &(ts
->hash_next
);
3682 ts
= tok_alloc_new(pts
, p1
, len
);
3686 cstr_reset(&tokcstr
);
3689 cstr_ccat(&tokcstr
, *p1
);
3695 while (isidnum_table
[c
]) {
3696 cstr_ccat(&tokcstr
, c
);
3699 ts
= tok_alloc(tokcstr
.data
, tokcstr
.size
);
3705 if (t
!= '\\' && t
!= '\'' && t
!= '\"') {
3707 goto parse_ident_fast
;
3710 if (c
== '\'' || c
== '\"') {
3714 cstr_reset(&tokcstr
);
3715 cstr_ccat(&tokcstr
, 'L');
3716 goto parse_ident_slow
;
3720 case '0': case '1': case '2': case '3':
3721 case '4': case '5': case '6': case '7':
3724 cstr_reset(&tokcstr
);
3725 /* after the first digit, accept digits, alpha, '.' or sign if
3726 prefixed by 'eEpP' */
3730 cstr_ccat(&tokcstr
, c
);
3732 if (!(isnum(c
) || isid(c
) || c
== '.' ||
3733 ((c
== '+' || c
== '-') &&
3734 (t
== 'e' || t
== 'E' || t
== 'p' || t
== 'P'))))
3737 /* We add a trailing '\0' to ease parsing */
3738 cstr_ccat(&tokcstr
, '\0');
3739 tokc
.cstr
= &tokcstr
;
3743 /* special dot handling because it can also start a number */
3746 cstr_reset(&tokcstr
);
3747 cstr_ccat(&tokcstr
, '.');
3749 } else if (c
== '.') {
3769 /* parse the string */
3771 p
= parse_pp_string(p
, sep
, &str
);
3772 cstr_ccat(&str
, '\0');
3774 /* eval the escape (should be done as TOK_PPNUM) */
3775 cstr_reset(&tokcstr
);
3776 parse_escape_string(&tokcstr
, str
.data
, is_long
);
3781 /* XXX: make it portable */
3785 char_size
= sizeof(nwchar_t
);
3786 if (tokcstr
.size
<= char_size
)
3787 error("empty character constant");
3788 if (tokcstr
.size
> 2 * char_size
)
3789 warning("multi-character character constant");
3791 tokc
.i
= *(int8_t *)tokcstr
.data
;
3794 tokc
.i
= *(nwchar_t
*)tokcstr
.data
;
3798 tokc
.cstr
= &tokcstr
;
3812 } else if (c
== '<') {
3830 } else if (c
== '>') {
3848 } else if (c
== '=') {
3861 } else if (c
== '=') {
3874 } else if (c
== '=') {
3887 } else if (c
== '=') {
3890 } else if (c
== '>') {
3898 PARSE2('!', '!', '=', TOK_NE
)
3899 PARSE2('=', '=', '=', TOK_EQ
)
3900 PARSE2('*', '*', '=', TOK_A_MUL
)
3901 PARSE2('%', '%', '=', TOK_A_MOD
)
3902 PARSE2('^', '^', '=', TOK_A_XOR
)
3904 /* comments or operator */
3908 p
= parse_comment(p
);
3910 } else if (c
== '/') {
3911 p
= parse_line_comment(p
);
3913 } else if (c
== '=') {
3933 case '$': /* only used in assembler */
3934 case '@': /* dito */
3939 error("unrecognized character \\x%02x", c
);
3945 #if defined(PARSE_DEBUG)
3946 printf("token = %s\n", get_tok_str(tok
, &tokc
));
3950 /* return next token without macro substitution. Can read input from
3952 static void next_nomacro(void)
3958 TOK_GET(tok
, macro_ptr
, tokc
);
3959 if (tok
== TOK_LINENUM
) {
3960 file
->line_num
= tokc
.i
;
3969 /* substitute args in macro_str and return allocated string */
3970 static int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
3972 int *st
, last_tok
, t
, notfirst
;
3981 TOK_GET(t
, macro_str
, cval
);
3986 TOK_GET(t
, macro_str
, cval
);
3989 s
= sym_find2(args
, t
);
3996 cstr_ccat(&cstr
, ' ');
3997 TOK_GET(t
, st
, cval
);
3998 cstr_cat(&cstr
, get_tok_str(t
, &cval
));
4001 cstr_ccat(&cstr
, '\0');
4003 printf("stringize: %s\n", (char *)cstr
.data
);
4007 tok_str_add2(&str
, TOK_STR
, &cval
);
4010 tok_str_add2(&str
, t
, &cval
);
4012 } else if (t
>= TOK_IDENT
) {
4013 s
= sym_find2(args
, t
);
4016 /* if '##' is present before or after, no arg substitution */
4017 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
4018 /* special case for var arg macros : ## eats the
4019 ',' if empty VA_ARGS variable. */
4020 /* XXX: test of the ',' is not 100%
4021 reliable. should fix it to avoid security
4023 if (gnu_ext
&& s
->type
.t
&&
4024 last_tok
== TOK_TWOSHARPS
&&
4025 str
.len
>= 2 && str
.str
[str
.len
- 2] == ',') {
4027 /* suppress ',' '##' */
4030 /* suppress '##' and add variable */
4038 TOK_GET(t1
, st
, cval
);
4041 tok_str_add2(&str
, t1
, &cval
);
4045 /* NOTE: the stream cannot be read when macro
4046 substituing an argument */
4047 macro_subst(&str
, nested_list
, st
, NULL
);
4050 tok_str_add(&str
, t
);
4053 tok_str_add2(&str
, t
, &cval
);
4057 tok_str_add(&str
, 0);
4061 static char const ab_month_name
[12][4] =
4063 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4064 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4067 /* do macro substitution of current token with macro 's' and add
4068 result to (tok_str,tok_len). 'nested_list' is the list of all
4069 macros we got inside to avoid recursing. Return non zero if no
4070 substitution needs to be done */
4071 static int macro_subst_tok(TokenString
*tok_str
,
4072 Sym
**nested_list
, Sym
*s
, struct macro_level
**can_read_stream
)
4074 Sym
*args
, *sa
, *sa1
;
4075 int mstr_allocated
, parlevel
, *mstr
, t
, t1
;
4082 /* if symbol is a macro, prepare substitution */
4083 /* special macros */
4084 if (tok
== TOK___LINE__
) {
4085 snprintf(buf
, sizeof(buf
), "%d", file
->line_num
);
4089 } else if (tok
== TOK___FILE__
) {
4090 cstrval
= file
->filename
;
4092 } else if (tok
== TOK___DATE__
|| tok
== TOK___TIME__
) {
4097 tm
= localtime(&ti
);
4098 if (tok
== TOK___DATE__
) {
4099 snprintf(buf
, sizeof(buf
), "%s %2d %d",
4100 ab_month_name
[tm
->tm_mon
], tm
->tm_mday
, tm
->tm_year
+ 1900);
4102 snprintf(buf
, sizeof(buf
), "%02d:%02d:%02d",
4103 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
);
4110 cstr_cat(&cstr
, cstrval
);
4111 cstr_ccat(&cstr
, '\0');
4113 tok_str_add2(tok_str
, t1
, &cval
);
4118 if (s
->type
.t
== MACRO_FUNC
) {
4119 /* NOTE: we do not use next_nomacro to avoid eating the
4120 next token. XXX: find better solution */
4124 if (t
== 0 && can_read_stream
) {
4125 /* end of macro stream: we must look at the token
4126 after in the file */
4127 struct macro_level
*ml
= *can_read_stream
;
4133 *can_read_stream
= ml
-> prev
;
4138 /* XXX: incorrect with comments */
4139 ch
= file
->buf_ptr
[0];
4140 while (is_space(ch
) || ch
== '\n')
4144 if (t
!= '(') /* no macro subst */
4147 /* argument macro */
4152 /* NOTE: empty args are allowed, except if no args */
4154 /* handle '()' case */
4155 if (!args
&& !sa
&& tok
== ')')
4158 error("macro '%s' used with too many args",
4159 get_tok_str(s
->v
, 0));
4162 /* NOTE: non zero sa->t indicates VA_ARGS */
4163 while ((parlevel
> 0 ||
4165 (tok
!= ',' || sa
->type
.t
))) &&
4169 else if (tok
== ')')
4171 if (tok
!= TOK_LINEFEED
)
4172 tok_str_add2(&str
, tok
, &tokc
);
4175 tok_str_add(&str
, 0);
4176 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, sa
->type
.t
, (int)str
.str
);
4179 /* special case for gcc var args: add an empty
4180 var arg argument if it is omitted */
4181 if (sa
&& sa
->type
.t
&& gnu_ext
)
4191 error("macro '%s' used with too few args",
4192 get_tok_str(s
->v
, 0));
4195 /* now subst each arg */
4196 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
4201 tok_str_free((int *)sa
->c
);
4207 sym_push2(nested_list
, s
->v
, 0, 0);
4208 macro_subst(tok_str
, nested_list
, mstr
, can_read_stream
);
4209 /* pop nested defined symbol */
4211 *nested_list
= sa1
->prev
;
4219 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4220 return the resulting string (which must be freed). */
4221 static inline int *macro_twosharps(const int *macro_str
)
4224 const int *macro_ptr1
, *start_macro_ptr
, *ptr
, *saved_macro_ptr
;
4226 const char *p1
, *p2
;
4228 TokenString macro_str1
;
4231 start_macro_ptr
= macro_str
;
4232 /* we search the first '##' */
4234 macro_ptr1
= macro_str
;
4235 TOK_GET(t
, macro_str
, cval
);
4236 /* nothing more to do if end of string */
4239 if (*macro_str
== TOK_TWOSHARPS
)
4243 /* we saw '##', so we need more processing to handle it */
4245 tok_str_new(¯o_str1
);
4249 /* add all tokens seen so far */
4250 for(ptr
= start_macro_ptr
; ptr
< macro_ptr1
;) {
4251 TOK_GET(t
, ptr
, cval
);
4252 tok_str_add2(¯o_str1
, t
, &cval
);
4254 saved_macro_ptr
= macro_ptr
;
4255 /* XXX: get rid of the use of macro_ptr here */
4256 macro_ptr
= (int *)macro_str
;
4258 while (*macro_ptr
== TOK_TWOSHARPS
) {
4260 macro_ptr1
= macro_ptr
;
4263 TOK_GET(t
, macro_ptr
, cval
);
4264 /* We concatenate the two tokens if we have an
4265 identifier or a preprocessing number */
4267 p1
= get_tok_str(tok
, &tokc
);
4268 cstr_cat(&cstr
, p1
);
4269 p2
= get_tok_str(t
, &cval
);
4270 cstr_cat(&cstr
, p2
);
4271 cstr_ccat(&cstr
, '\0');
4273 if ((tok
>= TOK_IDENT
|| tok
== TOK_PPNUM
) &&
4274 (t
>= TOK_IDENT
|| t
== TOK_PPNUM
)) {
4275 if (tok
== TOK_PPNUM
) {
4276 /* if number, then create a number token */
4277 /* NOTE: no need to allocate because
4278 tok_str_add2() does it */
4279 cstr_reset(&tokcstr
);
4282 tokc
.cstr
= &tokcstr
;
4284 /* if identifier, we must do a test to
4285 validate we have a correct identifier */
4286 if (t
== TOK_PPNUM
) {
4296 if (!isnum(c
) && !isid(c
))
4300 ts
= tok_alloc(cstr
.data
, strlen(cstr
.data
));
4301 tok
= ts
->tok
; /* modify current token */
4304 const char *str
= cstr
.data
;
4305 const unsigned char *q
;
4307 /* we look for a valid token */
4308 /* XXX: do more extensive checks */
4309 if (!strcmp(str
, ">>=")) {
4311 } else if (!strcmp(str
, "<<=")) {
4313 } else if (strlen(str
) == 2) {
4314 /* search in two bytes table */
4319 if (q
[0] == str
[0] && q
[1] == str
[1])
4326 /* NOTE: because get_tok_str use a static buffer,
4329 p1
= get_tok_str(tok
, &tokc
);
4330 cstr_cat(&cstr
, p1
);
4331 cstr_ccat(&cstr
, '\0');
4332 p2
= get_tok_str(t
, &cval
);
4333 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr
.data
, p2
);
4334 /* cannot merge tokens: just add them separately */
4335 tok_str_add2(¯o_str1
, tok
, &tokc
);
4336 /* XXX: free associated memory ? */
4343 tok_str_add2(¯o_str1
, tok
, &tokc
);
4348 macro_ptr
= (int *)saved_macro_ptr
;
4350 tok_str_add(¯o_str1
, 0);
4351 return macro_str1
.str
;
4355 /* do macro substitution of macro_str and add result to
4356 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4357 inside to avoid recursing. */
4358 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
4359 const int *macro_str
, struct macro_level
** can_read_stream
)
4366 struct macro_level ml
;
4368 /* first scan for '##' operator handling */
4370 macro_str1
= macro_twosharps(ptr
);
4374 /* NOTE: ptr == NULL can only happen if tokens are read from
4375 file stream due to a macro function call */
4378 TOK_GET(t
, ptr
, cval
);
4383 /* if nested substitution, do nothing */
4384 if (sym_find2(*nested_list
, t
))
4387 if (can_read_stream
)
4388 ml
.prev
= *can_read_stream
, *can_read_stream
= &ml
;
4389 macro_ptr
= (int *)ptr
;
4391 ret
= macro_subst_tok(tok_str
, nested_list
, s
, can_read_stream
);
4392 ptr
= (int *)macro_ptr
;
4394 if (can_read_stream
&& *can_read_stream
== &ml
)
4395 *can_read_stream
= ml
.prev
;
4400 tok_str_add2(tok_str
, t
, &cval
);
4404 tok_str_free(macro_str1
);
4407 /* return next token with macro substitution */
4408 static void next(void)
4410 Sym
*nested_list
, *s
;
4412 struct macro_level
*ml
;
4417 /* if not reading from macro substituted string, then try
4418 to substitute macros */
4419 if (tok
>= TOK_IDENT
&&
4420 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
4421 s
= define_find(tok
);
4423 /* we have a macro: we try to substitute */
4427 if (macro_subst_tok(&str
, &nested_list
, s
, &ml
) == 0) {
4428 /* substitution done, NOTE: maybe empty */
4429 tok_str_add(&str
, 0);
4430 macro_ptr
= str
.str
;
4431 macro_ptr_allocated
= str
.str
;
4438 /* end of macro or end of unget buffer */
4439 if (unget_buffer_enabled
) {
4440 macro_ptr
= unget_saved_macro_ptr
;
4441 unget_buffer_enabled
= 0;
4443 /* end of macro string: free it */
4444 tok_str_free(macro_ptr_allocated
);
4451 /* convert preprocessor tokens into C tokens */
4452 if (tok
== TOK_PPNUM
&&
4453 (parse_flags
& PARSE_FLAG_TOK_NUM
)) {
4454 parse_number((char *)tokc
.cstr
->data
);
4458 /* push back current token and set current token to 'last_tok'. Only
4459 identifier case handled for labels. */
4460 static inline void unget_tok(int last_tok
)
4464 unget_saved_macro_ptr
= macro_ptr
;
4465 unget_buffer_enabled
= 1;
4466 q
= unget_saved_buffer
;
4469 n
= tok_ext_size(tok
) - 1;
4472 *q
= 0; /* end of token string */
4477 void swap(int *p
, int *q
)
4485 void vsetc(CType
*type
, int r
, CValue
*vc
)
4489 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4490 error("memory full");
4491 /* cannot let cpu flags if other instruction are generated. Also
4492 avoid leaving VT_JMP anywhere except on the top of the stack
4493 because it would complicate the code generator. */
4494 if (vtop
>= vstack
) {
4495 v
= vtop
->r
& VT_VALMASK
;
4496 if (v
== VT_CMP
|| (v
& ~1) == VT_JMP
)
4502 vtop
->r2
= VT_CONST
;
4506 /* push integer constant */
4511 vsetc(&int_type
, VT_CONST
, &cval
);
4514 /* Return a static symbol pointing to a section */
4515 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
4516 unsigned long offset
, unsigned long size
)
4522 sym
= global_identifier_push(v
, type
->t
| VT_STATIC
, 0);
4523 sym
->type
.ref
= type
->ref
;
4524 sym
->r
= VT_CONST
| VT_SYM
;
4525 put_extern_sym(sym
, sec
, offset
, size
);
4529 /* push a reference to a section offset by adding a dummy symbol */
4530 static void vpush_ref(CType
*type
, Section
*sec
, unsigned long offset
, unsigned long size
)
4535 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4536 vtop
->sym
= get_sym_ref(type
, sec
, offset
, size
);
4539 /* define a new external reference to a symbol 'v' of type 'u' */
4540 static Sym
*external_global_sym(int v
, CType
*type
, int r
)
4546 /* push forward reference */
4547 s
= global_identifier_push(v
, type
->t
| VT_EXTERN
, 0);
4548 s
->type
.ref
= type
->ref
;
4549 s
->r
= r
| VT_CONST
| VT_SYM
;
4554 /* define a new external reference to a symbol 'v' of type 'u' */
4555 static Sym
*external_sym(int v
, CType
*type
, int r
)
4561 /* push forward reference */
4562 s
= sym_push(v
, type
, r
| VT_CONST
| VT_SYM
, 0);
4563 s
->type
.t
|= VT_EXTERN
;
4565 if (!is_compatible_types(&s
->type
, type
))
4566 error("incompatible types for redefinition of '%s'",
4567 get_tok_str(v
, NULL
));
4572 /* push a reference to global symbol v */
4573 static void vpush_global_sym(CType
*type
, int v
)
4578 sym
= external_global_sym(v
, type
, 0);
4580 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4584 void vset(CType
*type
, int r
, int v
)
4589 vsetc(type
, r
, &cval
);
4592 void vseti(int r
, int v
)
4608 void vpushv(SValue
*v
)
4610 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4611 error("memory full");
4621 /* save r to the memory stack, and mark it as being free */
4622 void save_reg(int r
)
4624 int l
, saved
, size
, align
;
4628 /* modify all stack values */
4631 for(p
=vstack
;p
<=vtop
;p
++) {
4632 if ((p
->r
& VT_VALMASK
) == r
||
4633 ((p
->type
.t
& VT_BTYPE
) == VT_LLONG
&& (p
->r2
& VT_VALMASK
) == r
)) {
4634 /* must save value on stack if not already done */
4636 /* NOTE: must reload 'r' because r might be equal to r2 */
4637 r
= p
->r
& VT_VALMASK
;
4638 /* store register in the stack */
4640 if ((p
->r
& VT_LVAL
) ||
4641 (!is_float(type
->t
) && (type
->t
& VT_BTYPE
) != VT_LLONG
))
4643 size
= type_size(type
, &align
);
4644 loc
= (loc
- size
) & -align
;
4645 sv
.type
.t
= type
->t
;
4646 sv
.r
= VT_LOCAL
| VT_LVAL
;
4649 #ifdef TCC_TARGET_I386
4650 /* x86 specific: need to pop fp register ST0 if saved */
4651 if (r
== TREG_ST0
) {
4652 o(0xd9dd); /* fstp %st(1) */
4655 /* special long long case */
4656 if ((type
->t
& VT_BTYPE
) == VT_LLONG
) {
4663 /* mark that stack entry as being saved on the stack */
4664 if (p
->r
& VT_LVAL
) {
4665 /* also clear the bounded flag because the
4666 relocation address of the function was stored in
4668 p
->r
= (p
->r
& ~(VT_VALMASK
| VT_BOUNDED
)) | VT_LLOCAL
;
4670 p
->r
= lvalue_type(p
->type
.t
) | VT_LOCAL
;
4678 /* find a register of class 'rc2' with at most one reference on stack.
4679 * If none, call get_reg(rc) */
4680 int get_reg_ex(int rc
, int rc2
)
4685 for(r
=0;r
<NB_REGS
;r
++) {
4686 if (reg_classes
[r
] & rc2
) {
4689 for(p
= vstack
; p
<= vtop
; p
++) {
4690 if ((p
->r
& VT_VALMASK
) == r
||
4691 (p
->r2
& VT_VALMASK
) == r
)
4701 /* find a free register of class 'rc'. If none, save one register */
4707 /* find a free register */
4708 for(r
=0;r
<NB_REGS
;r
++) {
4709 if (reg_classes
[r
] & rc
) {
4710 for(p
=vstack
;p
<=vtop
;p
++) {
4711 if ((p
->r
& VT_VALMASK
) == r
||
4712 (p
->r2
& VT_VALMASK
) == r
)
4720 /* no register left : free the first one on the stack (VERY
4721 IMPORTANT to start from the bottom to ensure that we don't
4722 spill registers used in gen_opi()) */
4723 for(p
=vstack
;p
<=vtop
;p
++) {
4724 r
= p
->r
& VT_VALMASK
;
4725 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
))
4727 /* also look at second register (if long long) */
4728 r
= p
->r2
& VT_VALMASK
;
4729 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
4735 /* Should never comes here */
4739 /* save registers up to (vtop - n) stack entry */
4740 void save_regs(int n
)
4745 for(p
= vstack
;p
<= p1
; p
++) {
4746 r
= p
->r
& VT_VALMASK
;
4753 /* move register 's' to 'r', and flush previous value of r to memory
4755 void move_reg(int r
, int s
)
4768 /* get address of vtop (vtop MUST BE an lvalue) */
4771 vtop
->r
&= ~VT_LVAL
;
4772 /* tricky: if saved lvalue, then we can go back to lvalue */
4773 if ((vtop
->r
& VT_VALMASK
) == VT_LLOCAL
)
4774 vtop
->r
= (vtop
->r
& ~(VT_VALMASK
| VT_LVAL_TYPE
)) | VT_LOCAL
| VT_LVAL
;
4777 #ifdef CONFIG_TCC_BCHECK
4778 /* generate lvalue bound code */
4784 vtop
->r
&= ~VT_MUSTBOUND
;
4785 /* if lvalue, then use checking code before dereferencing */
4786 if (vtop
->r
& VT_LVAL
) {
4787 /* if not VT_BOUNDED value, then make one */
4788 if (!(vtop
->r
& VT_BOUNDED
)) {
4789 lval_type
= vtop
->r
& (VT_LVAL_TYPE
| VT_LVAL
);
4790 /* must save type because we must set it to int to get pointer */
4792 vtop
->type
.t
= VT_INT
;
4795 gen_bounded_ptr_add();
4796 vtop
->r
|= lval_type
;
4799 /* then check for dereferencing */
4800 gen_bounded_ptr_deref();
4805 /* store vtop a register belonging to class 'rc'. lvalues are
4806 converted to values. Cannot be used if cannot be converted to
4807 register value (such as structures). */
4810 int r
, r2
, rc2
, bit_pos
, bit_size
, size
, align
, i
;
4811 unsigned long long ll
;
4813 /* NOTE: get_reg can modify vstack[] */
4814 if (vtop
->type
.t
& VT_BITFIELD
) {
4815 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
4816 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
4817 /* remove bit field info to avoid loops */
4818 vtop
->type
.t
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
4819 /* generate shifts */
4820 vpushi(32 - (bit_pos
+ bit_size
));
4822 vpushi(32 - bit_size
);
4823 /* NOTE: transformed to SHR if unsigned */
4827 if (is_float(vtop
->type
.t
) &&
4828 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4831 unsigned long offset
;
4832 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4836 /* XXX: unify with initializers handling ? */
4837 /* CPUs usually cannot use float constants, so we store them
4838 generically in data segment */
4839 size
= type_size(&vtop
->type
, &align
);
4840 offset
= (data_section
->data_offset
+ align
- 1) & -align
;
4841 data_section
->data_offset
= offset
;
4842 /* XXX: not portable yet */
4844 /* Zero pad x87 tenbyte long doubles */
4846 vtop
->c
.tab
[2] &= 0xffff;
4848 ptr
= section_ptr_add(data_section
, size
);
4850 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4854 ptr
[i
] = vtop
->c
.tab
[size
-1-i
];
4858 ptr
[i
] = vtop
->c
.tab
[i
];
4859 sym
= get_sym_ref(&vtop
->type
, data_section
, offset
, size
<< 2);
4860 vtop
->r
|= VT_LVAL
| VT_SYM
;
4864 #ifdef CONFIG_TCC_BCHECK
4865 if (vtop
->r
& VT_MUSTBOUND
)
4869 r
= vtop
->r
& VT_VALMASK
;
4870 /* need to reload if:
4872 - lvalue (need to dereference pointer)
4873 - already a register, but not in the right class */
4874 if (r
>= VT_CONST
||
4875 (vtop
->r
& VT_LVAL
) ||
4876 !(reg_classes
[r
] & rc
) ||
4877 ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
&&
4878 !(reg_classes
[vtop
->r2
] & rc
))) {
4880 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
4881 /* two register type load : expand to two words
4883 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4886 vtop
->c
.ui
= ll
; /* first word */
4888 vtop
->r
= r
; /* save register value */
4889 vpushi(ll
>> 32); /* second word */
4890 } else if (r
>= VT_CONST
|| /* XXX: test to VT_CONST incorrect ? */
4891 (vtop
->r
& VT_LVAL
)) {
4892 /* We do not want to modifier the long long
4893 pointer here, so the safest (and less
4894 efficient) is to save all the other registers
4895 in the stack. XXX: totally inefficient. */
4897 /* load from memory */
4900 vtop
[-1].r
= r
; /* save register value */
4901 /* increment pointer to get second word */
4902 vtop
->type
.t
= VT_INT
;
4908 /* move registers */
4911 vtop
[-1].r
= r
; /* save register value */
4912 vtop
->r
= vtop
[-1].r2
;
4914 /* allocate second register */
4921 /* write second register */
4923 } else if ((vtop
->r
& VT_LVAL
) && !is_float(vtop
->type
.t
)) {
4925 /* lvalue of scalar type : need to use lvalue type
4926 because of possible cast */
4929 /* compute memory access type */
4930 if (vtop
->r
& VT_LVAL_BYTE
)
4932 else if (vtop
->r
& VT_LVAL_SHORT
)
4934 if (vtop
->r
& VT_LVAL_UNSIGNED
)
4938 /* restore wanted type */
4941 /* one register type load */
4946 #ifdef TCC_TARGET_C67
4947 /* uses register pairs for doubles */
4948 if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
)
4955 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4956 void gv2(int rc1
, int rc2
)
4960 /* generate more generic register first. But VT_JMP or VT_CMP
4961 values must be generated first in all cases to avoid possible
4963 v
= vtop
[0].r
& VT_VALMASK
;
4964 if (v
!= VT_CMP
&& (v
& ~1) != VT_JMP
&& rc1
<= rc2
) {
4969 /* test if reload is needed for first register */
4970 if ((vtop
[-1].r
& VT_VALMASK
) >= VT_CONST
) {
4980 /* test if reload is needed for first register */
4981 if ((vtop
[0].r
& VT_VALMASK
) >= VT_CONST
) {
4987 /* expand long long on stack in two int registers */
4992 u
= vtop
->type
.t
& VT_UNSIGNED
;
4995 vtop
[0].r
= vtop
[-1].r2
;
4996 vtop
[0].r2
= VT_CONST
;
4997 vtop
[-1].r2
= VT_CONST
;
4998 vtop
[0].type
.t
= VT_INT
| u
;
4999 vtop
[-1].type
.t
= VT_INT
| u
;
5002 #ifdef TCC_TARGET_ARM
5003 /* expand long long on stack */
5004 void lexpand_nr(void)
5008 u
= vtop
->type
.t
& VT_UNSIGNED
;
5010 vtop
->r2
= VT_CONST
;
5011 vtop
->type
.t
= VT_INT
| u
;
5012 v
=vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
);
5013 if (v
== VT_CONST
) {
5014 vtop
[-1].c
.ui
= vtop
->c
.ull
;
5015 vtop
->c
.ui
= vtop
->c
.ull
>> 32;
5017 } else if (v
== (VT_LVAL
|VT_CONST
) || v
== (VT_LVAL
|VT_LOCAL
)) {
5019 vtop
->r
= vtop
[-1].r
;
5020 } else if (v
> VT_CONST
) {
5024 vtop
->r
= vtop
[-1].r2
;
5025 vtop
[-1].r2
= VT_CONST
;
5026 vtop
[-1].type
.t
= VT_INT
| u
;
5030 /* build a long long from two ints */
5033 gv2(RC_INT
, RC_INT
);
5034 vtop
[-1].r2
= vtop
[0].r
;
5035 vtop
[-1].type
.t
= t
;
5039 /* rotate n first stack elements to the bottom
5040 I1 ... In -> I2 ... In I1 [top is right]
5048 for(i
=-n
+1;i
!=0;i
++)
5049 vtop
[i
] = vtop
[i
+1];
5053 /* rotate n first stack elements to the top
5054 I1 ... In -> In I1 ... I(n-1) [top is right]
5062 for(i
= 0;i
< n
- 1; i
++)
5063 vtop
[-i
] = vtop
[-i
- 1];
5067 #ifdef TCC_TARGET_ARM
5068 /* like vrott but in other direction
5069 In ... I1 -> I(n-1) ... I1 In [top is right]
5077 for(i
= n
- 1; i
> 0; i
--)
5078 vtop
[-i
] = vtop
[-i
+ 1];
5083 /* pop stack value */
5087 v
= vtop
->r
& VT_VALMASK
;
5088 #ifdef TCC_TARGET_I386
5089 /* for x86, we need to pop the FP stack */
5090 if (v
== TREG_ST0
&& !nocode_wanted
) {
5091 o(0xd9dd); /* fstp %st(1) */
5094 if (v
== VT_JMP
|| v
== VT_JMPI
) {
5095 /* need to put correct jump if && or || without test */
5101 /* convert stack entry to register and duplicate its value in another
5109 if ((t
& VT_BTYPE
) == VT_LLONG
) {
5116 /* stack: H L L1 H1 */
5124 /* duplicate value */
5135 load(r1
, &sv
); /* move r to r1 */
5137 /* duplicates value */
5142 /* generate CPU independent (unsigned) long long operations */
5143 void gen_opl(int op
)
5145 int t
, a
, b
, op1
, c
, i
;
5152 func
= TOK___divdi3
;
5155 func
= TOK___udivdi3
;
5158 func
= TOK___moddi3
;
5161 func
= TOK___umoddi3
;
5163 /* call generic long long function */
5164 vpush_global_sym(&func_old_type
, func
);
5169 vtop
->r2
= REG_LRET
;
5182 /* stack: L1 H1 L2 H2 */
5187 vtop
[-2] = vtop
[-3];
5190 /* stack: H1 H2 L1 L2 */
5196 /* stack: H1 H2 L1 L2 ML MH */
5199 /* stack: ML MH H1 H2 L1 L2 */
5203 /* stack: ML MH H1 L2 H2 L1 */
5208 /* stack: ML MH M1 M2 */
5211 } else if (op
== '+' || op
== '-') {
5212 /* XXX: add non carry method too (for MIPS or alpha) */
5218 /* stack: H1 H2 (L1 op L2) */
5221 gen_op(op1
+ 1); /* TOK_xxxC2 */
5224 /* stack: H1 H2 (L1 op L2) */
5227 /* stack: (L1 op L2) H1 H2 */
5229 /* stack: (L1 op L2) (H1 op H2) */
5237 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
5238 t
= vtop
[-1].type
.t
;
5242 /* stack: L H shift */
5244 /* constant: simpler */
5245 /* NOTE: all comments are for SHL. the other cases are
5246 done by swaping words */
5257 if (op
!= TOK_SAR
) {
5290 /* XXX: should provide a faster fallback on x86 ? */
5293 func
= TOK___sardi3
;
5296 func
= TOK___shrdi3
;
5299 func
= TOK___shldi3
;
5305 /* compare operations */
5311 /* stack: L1 H1 L2 H2 */
5313 vtop
[-1] = vtop
[-2];
5315 /* stack: L1 L2 H1 H2 */
5318 /* when values are equal, we need to compare low words. since
5319 the jump is inverted, we invert the test too. */
5322 else if (op1
== TOK_GT
)
5324 else if (op1
== TOK_ULT
)
5326 else if (op1
== TOK_UGT
)
5331 if (op1
!= TOK_NE
) {
5335 /* generate non equal test */
5336 /* XXX: NOT PORTABLE yet */
5340 #if defined(TCC_TARGET_I386)
5341 b
= psym(0x850f, 0);
5342 #elif defined(TCC_TARGET_ARM)
5344 o(0x1A000000 | encbranch(ind
, 0, 1));
5345 #elif defined(TCC_TARGET_C67)
5346 error("not implemented");
5348 #error not supported
5352 /* compare low. Always unsigned */
5356 else if (op1
== TOK_LE
)
5358 else if (op1
== TOK_GT
)
5360 else if (op1
== TOK_GE
)
5370 /* handle integer constant optimizations and various machine
5372 void gen_opic(int op
)
5374 int c1
, c2
, t1
, t2
, n
, c
;
5376 long long l1
, l2
, l
;
5377 typedef unsigned long long U
;
5381 t1
= v1
->type
.t
& VT_BTYPE
;
5382 t2
= v2
->type
.t
& VT_BTYPE
;
5383 l1
= (t1
== VT_LLONG
) ? v1
->c
.ll
: v1
->c
.i
;
5384 l2
= (t2
== VT_LLONG
) ? v2
->c
.ll
: v2
->c
.i
;
5386 /* currently, we cannot do computations with forward symbols */
5387 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5388 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5391 case '+': l1
+= l2
; break;
5392 case '-': l1
-= l2
; break;
5393 case '&': l1
&= l2
; break;
5394 case '^': l1
^= l2
; break;
5395 case '|': l1
|= l2
; break;
5396 case '*': l1
*= l2
; break;
5403 /* if division by zero, generate explicit division */
5406 error("division by zero in constant");
5410 default: l1
/= l2
; break;
5411 case '%': l1
%= l2
; break;
5412 case TOK_UDIV
: l1
= (U
)l1
/ l2
; break;
5413 case TOK_UMOD
: l1
= (U
)l1
% l2
; break;
5416 case TOK_SHL
: l1
<<= l2
; break;
5417 case TOK_SHR
: l1
= (U
)l1
>> l2
; break;
5418 case TOK_SAR
: l1
>>= l2
; break;
5420 case TOK_ULT
: l1
= (U
)l1
< (U
)l2
; break;
5421 case TOK_UGE
: l1
= (U
)l1
>= (U
)l2
; break;
5422 case TOK_EQ
: l1
= l1
== l2
; break;
5423 case TOK_NE
: l1
= l1
!= l2
; break;
5424 case TOK_ULE
: l1
= (U
)l1
<= (U
)l2
; break;
5425 case TOK_UGT
: l1
= (U
)l1
> (U
)l2
; break;
5426 case TOK_LT
: l1
= l1
< l2
; break;
5427 case TOK_GE
: l1
= l1
>= l2
; break;
5428 case TOK_LE
: l1
= l1
<= l2
; break;
5429 case TOK_GT
: l1
= l1
> l2
; break;
5431 case TOK_LAND
: l1
= l1
&& l2
; break;
5432 case TOK_LOR
: l1
= l1
|| l2
; break;
5439 /* if commutative ops, put c2 as constant */
5440 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
5441 op
== '|' || op
== '*')) {
5443 c
= c1
, c1
= c2
, c2
= c
;
5444 l
= l1
, l1
= l2
, l2
= l
;
5446 /* Filter out NOP operations like x*1, x-0, x&-1... */
5447 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
5450 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
5451 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
5457 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
5458 /* try to use shifts instead of muls or divs */
5459 if (l2
> 0 && (l2
& (l2
- 1)) == 0) {
5468 else if (op
== TOK_PDIV
)
5474 } else if (c2
&& (op
== '+' || op
== '-') &&
5475 (vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) ==
5476 (VT_CONST
| VT_SYM
)) {
5477 /* symbol + constant case */
5484 if (!nocode_wanted
) {
5485 /* call low level op generator */
5486 if (t1
== VT_LLONG
|| t2
== VT_LLONG
)
5497 /* generate a floating point operation with constant propagation */
5498 void gen_opif(int op
)
5506 /* currently, we cannot do computations with forward symbols */
5507 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5508 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5510 if (v1
->type
.t
== VT_FLOAT
) {
5513 } else if (v1
->type
.t
== VT_DOUBLE
) {
5521 /* NOTE: we only do constant propagation if finite number (not
5522 NaN or infinity) (ANSI spec) */
5523 if (!ieee_finite(f1
) || !ieee_finite(f2
))
5527 case '+': f1
+= f2
; break;
5528 case '-': f1
-= f2
; break;
5529 case '*': f1
*= f2
; break;
5533 error("division by zero in constant");
5538 /* XXX: also handles tests ? */
5542 /* XXX: overflow test ? */
5543 if (v1
->type
.t
== VT_FLOAT
) {
5545 } else if (v1
->type
.t
== VT_DOUBLE
) {
5553 if (!nocode_wanted
) {
5561 static int pointed_size(CType
*type
)
5564 return type_size(pointed_type(type
), &align
);
5567 static inline int is_null_pointer(SValue
*p
)
5569 if ((p
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
5571 return ((p
->type
.t
& VT_BTYPE
) == VT_INT
&& p
->c
.i
== 0) ||
5572 ((p
->type
.t
& VT_BTYPE
) == VT_LLONG
&& p
->c
.ll
== 0);
5575 static inline int is_integer_btype(int bt
)
5577 return (bt
== VT_BYTE
|| bt
== VT_SHORT
||
5578 bt
== VT_INT
|| bt
== VT_LLONG
);
5581 /* check types for comparison or substraction of pointers */
5582 static void check_comparison_pointer_types(SValue
*p1
, SValue
*p2
, int op
)
5584 CType
*type1
, *type2
, tmp_type1
, tmp_type2
;
5587 /* null pointers are accepted for all comparisons as gcc */
5588 if (is_null_pointer(p1
) || is_null_pointer(p2
))
5592 bt1
= type1
->t
& VT_BTYPE
;
5593 bt2
= type2
->t
& VT_BTYPE
;
5594 /* accept comparison between pointer and integer with a warning */
5595 if ((is_integer_btype(bt1
) || is_integer_btype(bt2
)) && op
!= '-') {
5596 if (op
!= TOK_LOR
&& op
!= TOK_LAND
)
5597 warning("comparison between pointer and integer");
5601 /* both must be pointers or implicit function pointers */
5602 if (bt1
== VT_PTR
) {
5603 type1
= pointed_type(type1
);
5604 } else if (bt1
!= VT_FUNC
)
5605 goto invalid_operands
;
5607 if (bt2
== VT_PTR
) {
5608 type2
= pointed_type(type2
);
5609 } else if (bt2
!= VT_FUNC
) {
5611 error("invalid operands to binary %s", get_tok_str(op
, NULL
));
5613 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
5614 (type2
->t
& VT_BTYPE
) == VT_VOID
)
5618 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5619 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5620 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
5621 /* gcc-like error if '-' is used */
5623 goto invalid_operands
;
5625 warning("comparison of distinct pointer types lacks a cast");
5629 /* generic gen_op: handles types problems */
5632 int u
, t1
, t2
, bt1
, bt2
, t
;
5635 t1
= vtop
[-1].type
.t
;
5636 t2
= vtop
[0].type
.t
;
5637 bt1
= t1
& VT_BTYPE
;
5638 bt2
= t2
& VT_BTYPE
;
5640 if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
5641 /* at least one operand is a pointer */
5642 /* relationnal op: must be both pointers */
5643 if (op
>= TOK_ULT
&& op
<= TOK_LOR
) {
5644 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5645 /* pointers are handled are unsigned */
5646 t
= VT_INT
| VT_UNSIGNED
;
5649 /* if both pointers, then it must be the '-' op */
5650 if (bt1
== VT_PTR
&& bt2
== VT_PTR
) {
5652 error("cannot use pointers here");
5653 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5654 /* XXX: check that types are compatible */
5655 u
= pointed_size(&vtop
[-1].type
);
5657 /* set to integer type */
5658 vtop
->type
.t
= VT_INT
;
5662 /* exactly one pointer : must be '+' or '-'. */
5663 if (op
!= '-' && op
!= '+')
5664 error("cannot use pointers here");
5665 /* Put pointer as first operand */
5666 if (bt2
== VT_PTR
) {
5670 type1
= vtop
[-1].type
;
5671 /* XXX: cast to int ? (long long case) */
5672 vpushi(pointed_size(&vtop
[-1].type
));
5674 #ifdef CONFIG_TCC_BCHECK
5675 /* if evaluating constant expression, no code should be
5676 generated, so no bound check */
5677 if (do_bounds_check
&& !const_wanted
) {
5678 /* if bounded pointers, we generate a special code to
5685 gen_bounded_ptr_add();
5691 /* put again type if gen_opic() swaped operands */
5694 } else if (is_float(bt1
) || is_float(bt2
)) {
5695 /* compute bigger type and do implicit casts */
5696 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
5698 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
5703 /* floats can only be used for a few operations */
5704 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
5705 (op
< TOK_ULT
|| op
> TOK_GT
))
5706 error("invalid operands for binary operation");
5708 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
5709 /* cast to biggest op */
5711 /* convert to unsigned if it does not fit in a long long */
5712 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
5713 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
5717 /* integer operations */
5719 /* convert to unsigned if it does not fit in an integer */
5720 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
5721 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
5724 /* XXX: currently, some unsigned operations are explicit, so
5725 we modify them here */
5726 if (t
& VT_UNSIGNED
) {
5733 else if (op
== TOK_LT
)
5735 else if (op
== TOK_GT
)
5737 else if (op
== TOK_LE
)
5739 else if (op
== TOK_GE
)
5746 /* special case for shifts and long long: we keep the shift as
5748 if (op
== TOK_SHR
|| op
== TOK_SAR
|| op
== TOK_SHL
)
5755 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
5756 /* relationnal op: the result is an int */
5757 vtop
->type
.t
= VT_INT
;
5764 /* generic itof for unsigned long long case */
5765 void gen_cvt_itof1(int t
)
5767 if ((vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
)) ==
5768 (VT_LLONG
| VT_UNSIGNED
)) {
5771 vpush_global_sym(&func_old_type
, TOK___ulltof
);
5772 else if (t
== VT_DOUBLE
)
5773 vpush_global_sym(&func_old_type
, TOK___ulltod
);
5775 vpush_global_sym(&func_old_type
, TOK___ulltold
);
5785 /* generic ftoi for unsigned long long case */
5786 void gen_cvt_ftoi1(int t
)
5790 if (t
== (VT_LLONG
| VT_UNSIGNED
)) {
5791 /* not handled natively */
5792 st
= vtop
->type
.t
& VT_BTYPE
;
5794 vpush_global_sym(&func_old_type
, TOK___fixunssfdi
);
5795 else if (st
== VT_DOUBLE
)
5796 vpush_global_sym(&func_old_type
, TOK___fixunsdfdi
);
5798 vpush_global_sym(&func_old_type
, TOK___fixunsxfdi
);
5803 vtop
->r2
= REG_LRET
;
5809 /* force char or short cast */
5810 void force_charshort_cast(int t
)
5814 /* XXX: add optimization if lvalue : just change type and offset */
5819 if (t
& VT_UNSIGNED
) {
5820 vpushi((1 << bits
) - 1);
5826 /* result must be signed or the SAR is converted to an SHL
5827 This was not the case when "t" was a signed short
5828 and the last value on the stack was an unsigned int */
5829 vtop
->type
.t
&= ~VT_UNSIGNED
;
5835 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5836 static void gen_cast(CType
*type
)
5838 int sbt
, dbt
, sf
, df
, c
;
5840 /* special delayed cast for char/short */
5841 /* XXX: in some cases (multiple cascaded casts), it may still
5843 if (vtop
->r
& VT_MUSTCAST
) {
5844 vtop
->r
&= ~VT_MUSTCAST
;
5845 force_charshort_cast(vtop
->type
.t
);
5848 /* bitfields first get cast to ints */
5849 if (vtop
->type
.t
& VT_BITFIELD
) {
5853 dbt
= type
->t
& (VT_BTYPE
| VT_UNSIGNED
);
5854 sbt
= vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
);
5856 if (sbt
!= dbt
&& !nocode_wanted
) {
5859 c
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5861 /* convert from fp to fp */
5863 /* constant case: we can do it now */
5864 /* XXX: in ISOC, cannot do it if error in convert */
5865 if (dbt
== VT_FLOAT
&& sbt
== VT_DOUBLE
)
5866 vtop
->c
.f
= (float)vtop
->c
.d
;
5867 else if (dbt
== VT_FLOAT
&& sbt
== VT_LDOUBLE
)
5868 vtop
->c
.f
= (float)vtop
->c
.ld
;
5869 else if (dbt
== VT_DOUBLE
&& sbt
== VT_FLOAT
)
5870 vtop
->c
.d
= (double)vtop
->c
.f
;
5871 else if (dbt
== VT_DOUBLE
&& sbt
== VT_LDOUBLE
)
5872 vtop
->c
.d
= (double)vtop
->c
.ld
;
5873 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_FLOAT
)
5874 vtop
->c
.ld
= (long double)vtop
->c
.f
;
5875 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_DOUBLE
)
5876 vtop
->c
.ld
= (long double)vtop
->c
.d
;
5878 /* non constant case: generate code */
5882 /* convert int to fp */
5885 case VT_LLONG
| VT_UNSIGNED
:
5887 /* XXX: add const cases for long long */
5889 case VT_INT
| VT_UNSIGNED
:
5891 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.ui
; break;
5892 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.ui
; break;
5893 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.ui
; break;
5898 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.i
; break;
5899 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.i
; break;
5900 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.i
; break;
5906 #if !defined(TCC_TARGET_ARM)
5913 /* convert fp to int */
5914 if (dbt
== VT_BOOL
) {
5918 /* we handle char/short/etc... with generic code */
5919 if (dbt
!= (VT_INT
| VT_UNSIGNED
) &&
5920 dbt
!= (VT_LLONG
| VT_UNSIGNED
) &&
5925 case VT_LLONG
| VT_UNSIGNED
:
5927 /* XXX: add const cases for long long */
5929 case VT_INT
| VT_UNSIGNED
:
5931 case VT_FLOAT
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5932 case VT_DOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5933 case VT_LDOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5939 case VT_FLOAT
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5940 case VT_DOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5941 case VT_LDOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5949 if (dbt
== VT_INT
&& (type
->t
& (VT_BTYPE
| VT_UNSIGNED
)) != dbt
) {
5950 /* additional cast for char/short... */
5955 } else if ((dbt
& VT_BTYPE
) == VT_LLONG
) {
5956 if ((sbt
& VT_BTYPE
) != VT_LLONG
) {
5957 /* scalar to long long */
5959 if (sbt
== (VT_INT
| VT_UNSIGNED
))
5960 vtop
->c
.ll
= vtop
->c
.ui
;
5962 vtop
->c
.ll
= vtop
->c
.i
;
5964 /* machine independent conversion */
5966 /* generate high word */
5967 if (sbt
== (VT_INT
| VT_UNSIGNED
)) {
5975 /* patch second register */
5976 vtop
[-1].r2
= vtop
->r
;
5980 } else if (dbt
== VT_BOOL
) {
5981 /* scalar to bool */
5984 } else if ((dbt
& VT_BTYPE
) == VT_BYTE
||
5985 (dbt
& VT_BTYPE
) == VT_SHORT
) {
5986 if (sbt
== VT_PTR
) {
5987 vtop
->type
.t
= VT_INT
;
5988 warning("nonportable conversion from pointer to char/short");
5990 force_charshort_cast(dbt
);
5991 } else if ((dbt
& VT_BTYPE
) == VT_INT
) {
5993 if (sbt
== VT_LLONG
) {
5994 /* from long long: just take low order word */
5998 /* if lvalue and single word type, nothing to do because
5999 the lvalue already contains the real type size (see
6000 VT_LVAL_xxx constants) */
6002 } else if ((dbt
& VT_BTYPE
) == VT_PTR
&& !(vtop
->r
& VT_LVAL
)) {
6003 /* if we are casting between pointer types,
6004 we must update the VT_LVAL_xxx size */
6005 vtop
->r
= (vtop
->r
& ~VT_LVAL_TYPE
)
6006 | (lvalue_type(type
->ref
->type
.t
) & VT_LVAL_TYPE
);
6011 /* return type size. Put alignment at 'a' */
6012 static int type_size(CType
*type
, int *a
)
6017 bt
= type
->t
& VT_BTYPE
;
6018 if (bt
== VT_STRUCT
) {
6023 } else if (bt
== VT_PTR
) {
6024 if (type
->t
& VT_ARRAY
) {
6026 return type_size(&s
->type
, a
) * s
->c
;
6031 } else if (bt
== VT_LDOUBLE
) {
6033 return LDOUBLE_SIZE
;
6034 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
6035 #ifdef TCC_TARGET_I386
6037 #elif defined(TCC_TARGET_ARM)
6047 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
6050 } else if (bt
== VT_SHORT
) {
6054 /* char, void, function, _Bool */
6060 /* return the pointed type of t */
6061 static inline CType
*pointed_type(CType
*type
)
6063 return &type
->ref
->type
;
6066 /* modify type so that its it is a pointer to type. */
6067 static void mk_pointer(CType
*type
)
6070 s
= sym_push(SYM_FIELD
, type
, 0, -1);
6071 type
->t
= VT_PTR
| (type
->t
& ~VT_TYPE
);
6075 /* compare function types. OLD functions match any new functions */
6076 static int is_compatible_func(CType
*type1
, CType
*type2
)
6082 if (!is_compatible_types(&s1
->type
, &s2
->type
))
6084 /* check func_call */
6087 /* XXX: not complete */
6088 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
6092 while (s1
!= NULL
) {
6095 if (!is_compatible_parameter_types(&s1
->type
, &s2
->type
))
6105 /* return true if type1 and type2 are the same. If unqualified is
6106 true, qualifiers on the types are ignored.
6108 - enums are not checked as gcc __builtin_types_compatible_p ()
6110 static int compare_types(CType
*type1
, CType
*type2
, int unqualified
)
6114 t1
= type1
->t
& VT_TYPE
;
6115 t2
= type2
->t
& VT_TYPE
;
6117 /* strip qualifiers before comparing */
6118 t1
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6119 t2
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6121 /* XXX: bitfields ? */
6124 /* test more complicated cases */
6125 bt1
= t1
& VT_BTYPE
;
6126 if (bt1
== VT_PTR
) {
6127 type1
= pointed_type(type1
);
6128 type2
= pointed_type(type2
);
6129 return is_compatible_types(type1
, type2
);
6130 } else if (bt1
== VT_STRUCT
) {
6131 return (type1
->ref
== type2
->ref
);
6132 } else if (bt1
== VT_FUNC
) {
6133 return is_compatible_func(type1
, type2
);
6139 /* return true if type1 and type2 are exactly the same (including
6142 static int is_compatible_types(CType
*type1
, CType
*type2
)
6144 return compare_types(type1
,type2
,0);
6147 /* return true if type1 and type2 are the same (ignoring qualifiers).
6149 static int is_compatible_parameter_types(CType
*type1
, CType
*type2
)
6151 return compare_types(type1
,type2
,1);
6154 /* print a type. If 'varstr' is not NULL, then the variable is also
6155 printed in the type */
6157 /* XXX: add array and function pointers */
6158 void type_to_str(char *buf
, int buf_size
,
6159 CType
*type
, const char *varstr
)
6166 t
= type
->t
& VT_TYPE
;
6169 if (t
& VT_CONSTANT
)
6170 pstrcat(buf
, buf_size
, "const ");
6171 if (t
& VT_VOLATILE
)
6172 pstrcat(buf
, buf_size
, "volatile ");
6173 if (t
& VT_UNSIGNED
)
6174 pstrcat(buf
, buf_size
, "unsigned ");
6204 tstr
= "long double";
6206 pstrcat(buf
, buf_size
, tstr
);
6210 if (bt
== VT_STRUCT
)
6214 pstrcat(buf
, buf_size
, tstr
);
6215 v
= type
->ref
->v
& ~SYM_STRUCT
;
6216 if (v
>= SYM_FIRST_ANOM
)
6217 pstrcat(buf
, buf_size
, "<anonymous>");
6219 pstrcat(buf
, buf_size
, get_tok_str(v
, NULL
));
6223 type_to_str(buf
, buf_size
, &s
->type
, varstr
);
6224 pstrcat(buf
, buf_size
, "(");
6226 while (sa
!= NULL
) {
6227 type_to_str(buf1
, sizeof(buf1
), &sa
->type
, NULL
);
6228 pstrcat(buf
, buf_size
, buf1
);
6231 pstrcat(buf
, buf_size
, ", ");
6233 pstrcat(buf
, buf_size
, ")");
6237 pstrcpy(buf1
, sizeof(buf1
), "*");
6239 pstrcat(buf1
, sizeof(buf1
), varstr
);
6240 type_to_str(buf
, buf_size
, &s
->type
, buf1
);
6244 pstrcat(buf
, buf_size
, " ");
6245 pstrcat(buf
, buf_size
, varstr
);
6250 /* verify type compatibility to store vtop in 'dt' type, and generate
6252 static void gen_assign_cast(CType
*dt
)
6254 CType
*st
, *type1
, *type2
, tmp_type1
, tmp_type2
;
6255 char buf1
[256], buf2
[256];
6258 st
= &vtop
->type
; /* source type */
6259 dbt
= dt
->t
& VT_BTYPE
;
6260 sbt
= st
->t
& VT_BTYPE
;
6261 if (dt
->t
& VT_CONSTANT
)
6262 warning("assignment of read-only location");
6265 /* special cases for pointers */
6266 /* '0' can also be a pointer */
6267 if (is_null_pointer(vtop
))
6269 /* accept implicit pointer to integer cast with warning */
6270 if (is_integer_btype(sbt
)) {
6271 warning("assignment makes pointer from integer without a cast");
6274 type1
= pointed_type(dt
);
6275 /* a function is implicitely a function pointer */
6276 if (sbt
== VT_FUNC
) {
6277 if ((type1
->t
& VT_BTYPE
) != VT_VOID
&&
6278 !is_compatible_types(pointed_type(dt
), st
))
6285 type2
= pointed_type(st
);
6286 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
6287 (type2
->t
& VT_BTYPE
) == VT_VOID
) {
6288 /* void * can match anything */
6290 /* exact type match, except for unsigned */
6293 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6294 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6295 if (!is_compatible_types(&tmp_type1
, &tmp_type2
))
6296 warning("assignment from incompatible pointer type");
6298 /* check const and volatile */
6299 if ((!(type1
->t
& VT_CONSTANT
) && (type2
->t
& VT_CONSTANT
)) ||
6300 (!(type1
->t
& VT_VOLATILE
) && (type2
->t
& VT_VOLATILE
)))
6301 warning("assignment discards qualifiers from pointer target type");
6307 if (sbt
== VT_PTR
|| sbt
== VT_FUNC
) {
6308 warning("assignment makes integer from pointer without a cast");
6310 /* XXX: more tests */
6315 tmp_type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6316 tmp_type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6317 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
6319 type_to_str(buf1
, sizeof(buf1
), st
, NULL
);
6320 type_to_str(buf2
, sizeof(buf2
), dt
, NULL
);
6321 error("cannot cast '%s' to '%s'", buf1
, buf2
);
6329 /* store vtop in lvalue pushed on stack */
6332 int sbt
, dbt
, ft
, r
, t
, size
, align
, bit_size
, bit_pos
, rc
, delayed_cast
;
6334 ft
= vtop
[-1].type
.t
;
6335 sbt
= vtop
->type
.t
& VT_BTYPE
;
6336 dbt
= ft
& VT_BTYPE
;
6337 if (((sbt
== VT_INT
|| sbt
== VT_SHORT
) && dbt
== VT_BYTE
) ||
6338 (sbt
== VT_INT
&& dbt
== VT_SHORT
)) {
6339 /* optimize char/short casts */
6340 delayed_cast
= VT_MUSTCAST
;
6341 vtop
->type
.t
= ft
& VT_TYPE
;
6342 /* XXX: factorize */
6343 if (ft
& VT_CONSTANT
)
6344 warning("assignment of read-only location");
6347 if (!(ft
& VT_BITFIELD
))
6348 gen_assign_cast(&vtop
[-1].type
);
6351 if (sbt
== VT_STRUCT
) {
6352 /* if structure, only generate pointer */
6353 /* structure assignment : generate memcpy */
6354 /* XXX: optimize if small size */
6355 if (!nocode_wanted
) {
6356 size
= type_size(&vtop
->type
, &align
);
6360 vpush_global_sym(&func_old_type
, TOK_memcpy8
);
6361 else if(!(align
& 3))
6362 vpush_global_sym(&func_old_type
, TOK_memcpy4
);
6365 vpush_global_sym(&func_old_type
, TOK_memcpy
);
6369 vtop
->type
.t
= VT_INT
;
6373 vtop
->type
.t
= VT_INT
;
6385 /* leave source on stack */
6386 } else if (ft
& VT_BITFIELD
) {
6387 /* bitfield store handling */
6388 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
6389 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
6390 /* remove bit field info to avoid loops */
6391 vtop
[-1].type
.t
= ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
6393 /* duplicate source into other register */
6398 /* duplicate destination */
6400 vtop
[-1] = vtop
[-2];
6402 /* mask and shift source */
6403 vpushi((1 << bit_size
) - 1);
6407 /* load destination, mask and or with source */
6409 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
6415 /* pop off shifted source from "duplicate source..." above */
6419 #ifdef CONFIG_TCC_BCHECK
6420 /* bound check case */
6421 if (vtop
[-1].r
& VT_MUSTBOUND
) {
6427 if (!nocode_wanted
) {
6431 r
= gv(rc
); /* generate value */
6432 /* if lvalue was saved on stack, must read it */
6433 if ((vtop
[-1].r
& VT_VALMASK
) == VT_LLOCAL
) {
6435 t
= get_reg(RC_INT
);
6437 sv
.r
= VT_LOCAL
| VT_LVAL
;
6438 sv
.c
.ul
= vtop
[-1].c
.ul
;
6440 vtop
[-1].r
= t
| VT_LVAL
;
6443 /* two word case handling : store second register at word + 4 */
6444 if ((ft
& VT_BTYPE
) == VT_LLONG
) {
6446 /* convert to int to increment easily */
6447 vtop
->type
.t
= VT_INT
;
6453 /* XXX: it works because r2 is spilled last ! */
6454 store(vtop
->r2
, vtop
- 1);
6458 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
6459 vtop
->r
|= delayed_cast
;
6463 /* post defines POST/PRE add. c is the token ++ or -- */
6464 void inc(int post
, int c
)
6467 vdup(); /* save lvalue */
6469 gv_dup(); /* duplicate value */
6474 vpushi(c
- TOK_MID
);
6476 vstore(); /* store value */
6478 vpop(); /* if post op, return saved value */
6481 /* Parse GNUC __attribute__ extension. Currently, the following
6482 extensions are recognized:
6483 - aligned(n) : set data/function alignment.
6484 - packed : force data alignment to 1
6485 - section(x) : generate data/code in this section.
6486 - unused : currently ignored, but may be used someday.
6487 - regparm(n) : pass function parameters in registers (i386 only)
6489 static void parse_attribute(AttributeDef
*ad
)
6493 while (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
) {
6497 while (tok
!= ')') {
6498 if (tok
< TOK_IDENT
)
6499 expect("attribute name");
6507 expect("section name");
6508 ad
->section
= find_section(tcc_state
, (char *)tokc
.cstr
->data
);
6517 if (n
<= 0 || (n
& (n
- 1)) != 0)
6518 error("alignment must be a positive power of two");
6531 /* currently, no need to handle it because tcc does not
6532 track unused objects */
6536 /* currently, no need to handle it because tcc does not
6537 track unused objects */
6542 ad
->func_call
= FUNC_CDECL
;
6547 ad
->func_call
= FUNC_STDCALL
;
6549 #ifdef TCC_TARGET_I386
6559 ad
->func_call
= FUNC_FASTCALL1
+ n
- 1;
6565 ad
->func_call
= FUNC_FASTCALLW
;
6572 if (tcc_state
->warn_unsupported
)
6573 warning("'%s' attribute ignored", get_tok_str(t
, NULL
));
6574 /* skip parameters */
6576 int parenthesis
= 0;
6580 else if (tok
== ')')
6583 } while (parenthesis
&& tok
!= -1);
6596 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6597 static void struct_decl(CType
*type
, int u
)
6599 int a
, v
, size
, align
, maxalign
, c
, offset
;
6600 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
;
6601 Sym
*s
, *ss
, *ass
, **ps
;
6605 a
= tok
; /* save decl type */
6610 /* struct already defined ? return it */
6612 expect("struct/union/enum name");
6616 error("invalid type");
6623 /* we put an undefined size for struct/union */
6624 s
= sym_push(v
| SYM_STRUCT
, &type1
, 0, -1);
6625 s
->r
= 0; /* default alignment is zero as gcc */
6626 /* put struct/union/enum name in type */
6634 error("struct/union/enum already defined");
6635 /* cannot be empty */
6637 /* non empty enums are not allowed */
6638 if (a
== TOK_ENUM
) {
6642 expect("identifier");
6648 /* enum symbols have static storage */
6649 ss
= sym_push(v
, &int_type
, VT_CONST
, c
);
6650 ss
->type
.t
|= VT_STATIC
;
6655 /* NOTE: we accept a trailing comma */
6665 while (tok
!= '}') {
6666 parse_btype(&btype
, &ad
);
6672 type_decl(&type1
, &ad
, &v
, TYPE_DIRECT
| TYPE_ABSTRACT
);
6673 if (v
== 0 && (type1
.t
& VT_BTYPE
) != VT_STRUCT
)
6674 expect("identifier");
6675 if ((type1
.t
& VT_BTYPE
) == VT_FUNC
||
6676 (type1
.t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
| VT_INLINE
)))
6677 error("invalid type for '%s'",
6678 get_tok_str(v
, NULL
));
6682 bit_size
= expr_const();
6683 /* XXX: handle v = 0 case for messages */
6685 error("negative width in bit-field '%s'",
6686 get_tok_str(v
, NULL
));
6687 if (v
&& bit_size
== 0)
6688 error("zero width for bit-field '%s'",
6689 get_tok_str(v
, NULL
));
6691 size
= type_size(&type1
, &align
);
6693 if (align
< ad
.aligned
)
6695 } else if (ad
.packed
) {
6697 } else if (*tcc_state
->pack_stack_ptr
) {
6698 if (align
> *tcc_state
->pack_stack_ptr
)
6699 align
= *tcc_state
->pack_stack_ptr
;
6702 if (bit_size
>= 0) {
6703 bt
= type1
.t
& VT_BTYPE
;
6709 error("bitfields must have scalar type");
6711 if (bit_size
> bsize
) {
6712 error("width of '%s' exceeds its type",
6713 get_tok_str(v
, NULL
));
6714 } else if (bit_size
== bsize
) {
6715 /* no need for bit fields */
6717 } else if (bit_size
== 0) {
6718 /* XXX: what to do if only padding in a
6720 /* zero size: means to pad */
6724 /* we do not have enough room ? */
6725 if ((bit_pos
+ bit_size
) > bsize
)
6728 /* XXX: handle LSB first */
6729 type1
.t
|= VT_BITFIELD
|
6730 (bit_pos
<< VT_STRUCT_SHIFT
) |
6731 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
6732 bit_pos
+= bit_size
;
6737 if (v
!= 0 || (type1
.t
& VT_BTYPE
) == VT_STRUCT
) {
6738 /* add new memory data only if starting
6740 if (lbit_pos
== 0) {
6741 if (a
== TOK_STRUCT
) {
6742 c
= (c
+ align
- 1) & -align
;
6751 if (align
> maxalign
)
6755 printf("add field %s offset=%d",
6756 get_tok_str(v
, NULL
), offset
);
6757 if (type1
.t
& VT_BITFIELD
) {
6758 printf(" pos=%d size=%d",
6759 (type1
.t
>> VT_STRUCT_SHIFT
) & 0x3f,
6760 (type1
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
6765 if (v
== 0 && (type1
.t
& VT_BTYPE
) == VT_STRUCT
) {
6767 while ((ass
= ass
->next
) != NULL
) {
6768 ss
= sym_push(ass
->v
, &ass
->type
, 0, offset
+ ass
->c
);
6773 ss
= sym_push(v
| SYM_FIELD
, &type1
, 0, offset
);
6777 if (tok
== ';' || tok
== TOK_EOF
)
6784 /* store size and alignment */
6785 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
6791 /* return 0 if no type declaration. otherwise, return the basic type
6794 static int parse_btype(CType
*type
, AttributeDef
*ad
)
6796 int t
, u
, type_found
, typespec_found
, typedef_found
;
6800 memset(ad
, 0, sizeof(AttributeDef
));
6808 /* currently, we really ignore extension */
6818 if ((t
& VT_BTYPE
) != 0)
6819 error("too many basic types");
6835 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
6836 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6837 } else if ((t
& VT_BTYPE
) == VT_LONG
) {
6838 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
6852 if ((t
& VT_BTYPE
) == VT_LONG
) {
6853 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6860 struct_decl(&type1
, VT_ENUM
);
6863 type
->ref
= type1
.ref
;
6867 struct_decl(&type1
, VT_STRUCT
);
6870 /* type modifiers */
6923 /* GNUC attribute */
6924 case TOK_ATTRIBUTE1
:
6925 case TOK_ATTRIBUTE2
:
6926 parse_attribute(ad
);
6933 parse_expr_type(&type1
);
6936 if (typespec_found
|| typedef_found
)
6939 if (!s
|| !(s
->type
.t
& VT_TYPEDEF
))
6942 t
|= (s
->type
.t
& ~VT_TYPEDEF
);
6943 type
->ref
= s
->type
.ref
;
6951 if ((t
& (VT_SIGNED
|VT_UNSIGNED
)) == (VT_SIGNED
|VT_UNSIGNED
))
6952 error("signed and unsigned modifier");
6953 if (tcc_state
->char_is_unsigned
) {
6954 if ((t
& (VT_SIGNED
|VT_UNSIGNED
|VT_BTYPE
)) == VT_BYTE
)
6959 /* long is never used as type */
6960 if ((t
& VT_BTYPE
) == VT_LONG
)
6961 t
= (t
& ~VT_BTYPE
) | VT_INT
;
6966 /* convert a function parameter type (array to pointer and function to
6967 function pointer) */
6968 static inline void convert_parameter_type(CType
*pt
)
6970 /* remove const and volatile qualifiers (XXX: const could be used
6971 to indicate a const function parameter */
6972 pt
->t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6973 /* array must be transformed to pointer according to ANSI C */
6975 if ((pt
->t
& VT_BTYPE
) == VT_FUNC
) {
6980 static void post_type(CType
*type
, AttributeDef
*ad
)
6983 Sym
**plast
, *s
, *first
;
6988 /* function declaration */
6995 /* read param name and compute offset */
6996 if (l
!= FUNC_OLD
) {
6997 if (!parse_btype(&pt
, &ad1
)) {
6999 error("invalid type");
7006 if ((pt
.t
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
7008 type_decl(&pt
, &ad1
, &n
, TYPE_DIRECT
| TYPE_ABSTRACT
);
7009 if ((pt
.t
& VT_BTYPE
) == VT_VOID
)
7010 error("parameter declared as void");
7015 expect("identifier");
7019 convert_parameter_type(&pt
);
7020 s
= sym_push(n
| SYM_FIELD
, &pt
, 0, 0);
7026 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
7033 /* if no parameters, then old type prototype */
7037 t1
= type
->t
& VT_STORAGE
;
7038 /* NOTE: const is ignored in returned type as it has a special
7039 meaning in gcc / C++ */
7040 type
->t
&= ~(VT_STORAGE
| VT_CONSTANT
);
7041 post_type(type
, ad
);
7042 /* we push a anonymous symbol which will contain the function prototype */
7043 s
= sym_push(SYM_FIELD
, type
, ad
->func_call
, l
);
7045 type
->t
= t1
| VT_FUNC
;
7047 } else if (tok
== '[') {
7048 /* array definition */
7054 error("invalid array size");
7057 /* parse next post type */
7058 t1
= type
->t
& VT_STORAGE
;
7059 type
->t
&= ~VT_STORAGE
;
7060 post_type(type
, ad
);
7062 /* we push a anonymous symbol which will contain the array
7064 s
= sym_push(SYM_FIELD
, type
, 0, n
);
7065 type
->t
= t1
| VT_ARRAY
| VT_PTR
;
7070 /* Parse a type declaration (except basic type), and return the type
7071 in 'type'. 'td' is a bitmask indicating which kind of type decl is
7072 expected. 'type' should contain the basic type. 'ad' is the
7073 attribute definition of the basic type. It can be modified by
7076 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
)
7079 CType type1
, *type2
;
7082 while (tok
== '*') {
7090 qualifiers
|= VT_CONSTANT
;
7095 qualifiers
|= VT_VOLATILE
;
7103 type
->t
|= qualifiers
;
7106 /* XXX: clarify attribute handling */
7107 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7108 parse_attribute(ad
);
7110 /* recursive type */
7111 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7112 type1
.t
= 0; /* XXX: same as int */
7115 /* XXX: this is not correct to modify 'ad' at this point, but
7116 the syntax is not clear */
7117 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7118 parse_attribute(ad
);
7119 type_decl(&type1
, ad
, v
, td
);
7122 /* type identifier */
7123 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
7127 if (!(td
& TYPE_ABSTRACT
))
7128 expect("identifier");
7132 post_type(type
, ad
);
7133 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7134 parse_attribute(ad
);
7137 /* append type at the end of type1 */
7150 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7151 static int lvalue_type(int t
)
7156 if (bt
== VT_BYTE
|| bt
== VT_BOOL
)
7158 else if (bt
== VT_SHORT
)
7162 if (t
& VT_UNSIGNED
)
7163 r
|= VT_LVAL_UNSIGNED
;
7167 /* indirection with full error checking and bound check */
7168 static void indir(void)
7170 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
) {
7171 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FUNC
)
7175 if ((vtop
->r
& VT_LVAL
) && !nocode_wanted
)
7177 vtop
->type
= *pointed_type(&vtop
->type
);
7178 /* Arrays and functions are never lvalues */
7179 if (!(vtop
->type
.t
& VT_ARRAY
)
7180 && (vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
) {
7181 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7182 /* if bound checking, the referenced pointer must be checked */
7183 if (do_bounds_check
)
7184 vtop
->r
|= VT_MUSTBOUND
;
7188 /* pass a parameter to a function and do type checking and casting */
7189 static void gfunc_param_typed(Sym
*func
, Sym
*arg
)
7194 func_type
= func
->c
;
7195 if (func_type
== FUNC_OLD
||
7196 (func_type
== FUNC_ELLIPSIS
&& arg
== NULL
)) {
7197 /* default casting : only need to convert float to double */
7198 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FLOAT
) {
7202 } else if (arg
== NULL
) {
7203 error("too many arguments to function");
7206 type
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
7207 gen_assign_cast(&type
);
7211 /* parse an expression of the form '(type)' or '(expr)' and return its
7213 static void parse_expr_type(CType
*type
)
7219 if (parse_btype(type
, &ad
)) {
7220 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7227 static void parse_type(CType
*type
)
7232 if (!parse_btype(type
, &ad
)) {
7235 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7238 static void vpush_tokc(int t
)
7242 vsetc(&type
, VT_CONST
, &tokc
);
7245 static void unary(void)
7247 int n
, t
, align
, size
, r
;
7252 /* XXX: GCC 2.95.3 does not generate a table although it should be
7266 vpush_tokc(VT_INT
| VT_UNSIGNED
);
7270 vpush_tokc(VT_LLONG
);
7274 vpush_tokc(VT_LLONG
| VT_UNSIGNED
);
7278 vpush_tokc(VT_FLOAT
);
7282 vpush_tokc(VT_DOUBLE
);
7286 vpush_tokc(VT_LDOUBLE
);
7289 case TOK___FUNCTION__
:
7291 goto tok_identifier
;
7297 /* special function name identifier */
7298 len
= strlen(funcname
) + 1;
7299 /* generate char[len] type */
7304 vpush_ref(&type
, data_section
, data_section
->data_offset
, len
);
7305 ptr
= section_ptr_add(data_section
, len
);
7306 memcpy(ptr
, funcname
, len
);
7311 #ifdef TCC_TARGET_PE
7312 t
= VT_SHORT
| VT_UNSIGNED
;
7318 /* string parsing */
7321 if (tcc_state
->warn_write_strings
)
7326 memset(&ad
, 0, sizeof(AttributeDef
));
7327 decl_initializer_alloc(&type
, &ad
, VT_CONST
, 2, 0, 0);
7332 if (parse_btype(&type
, &ad
)) {
7333 type_decl(&type
, &ad
, &n
, TYPE_ABSTRACT
);
7335 /* check ISOC99 compound literal */
7337 /* data is allocated locally by default */
7342 /* all except arrays are lvalues */
7343 if (!(type
.t
& VT_ARRAY
))
7344 r
|= lvalue_type(type
.t
);
7345 memset(&ad
, 0, sizeof(AttributeDef
));
7346 decl_initializer_alloc(&type
, &ad
, r
, 1, 0, 0);
7351 } else if (tok
== '{') {
7352 /* save all registers */
7354 /* statement expression : we do not accept break/continue
7355 inside as GCC does */
7356 block(NULL
, NULL
, NULL
, NULL
, 0, 1);
7371 /* functions names must be treated as function pointers,
7372 except for unary '&' and sizeof. Since we consider that
7373 functions are not lvalues, we only have to handle it
7374 there and in function calls. */
7375 /* arrays can also be used although they are not lvalues */
7376 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
&&
7377 !(vtop
->type
.t
& VT_ARRAY
) && !(vtop
->type
.t
& VT_LLOCAL
))
7379 mk_pointer(&vtop
->type
);
7385 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
)
7386 vtop
->c
.i
= !vtop
->c
.i
;
7387 else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
7388 vtop
->c
.i
= vtop
->c
.i
^ 1;
7391 vseti(VT_JMP
, gtst(1, 0));
7402 /* in order to force cast, we add zero */
7404 if ((vtop
->type
.t
& VT_BTYPE
) == VT_PTR
)
7405 error("pointer not accepted for unary plus");
7415 parse_expr_type(&type
);
7419 size
= type_size(&type
, &align
);
7420 if (t
== TOK_SIZEOF
) {
7422 error("sizeof applied to an incomplete type");
7427 vtop
->type
.t
|= VT_UNSIGNED
;
7430 case TOK_builtin_types_compatible_p
:
7439 type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7440 type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7441 vpushi(is_compatible_types(&type1
, &type2
));
7444 case TOK_builtin_constant_p
:
7446 int saved_nocode_wanted
, res
;
7449 saved_nocode_wanted
= nocode_wanted
;
7452 res
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
7454 nocode_wanted
= saved_nocode_wanted
;
7474 goto tok_identifier
;
7476 /* allow to take the address of a label */
7477 if (tok
< TOK_UIDENT
)
7478 expect("label identifier");
7479 s
= label_find(tok
);
7481 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
7483 if (s
->r
== LABEL_DECLARED
)
7484 s
->r
= LABEL_FORWARD
;
7487 s
->type
.t
= VT_VOID
;
7488 mk_pointer(&s
->type
);
7489 s
->type
.t
|= VT_STATIC
;
7491 vset(&s
->type
, VT_CONST
| VT_SYM
, 0);
7500 expect("identifier");
7504 error("'%s' undeclared", get_tok_str(t
, NULL
));
7505 /* for simple function calls, we tolerate undeclared
7506 external reference to int() function */
7507 if (tcc_state
->warn_implicit_function_declaration
)
7508 warning("implicit declaration of function '%s'",
7509 get_tok_str(t
, NULL
));
7510 s
= external_global_sym(t
, &func_old_type
, 0);
7512 if ((s
->type
.t
& (VT_STATIC
| VT_INLINE
| VT_BTYPE
)) ==
7513 (VT_STATIC
| VT_INLINE
| VT_FUNC
)) {
7514 /* if referencing an inline function, then we generate a
7515 symbol to it if not already done. It will have the
7516 effect to generate code for it at the end of the
7517 compilation unit. Inline function as always
7518 generated in the text section. */
7520 put_extern_sym(s
, text_section
, 0, 0);
7521 r
= VT_SYM
| VT_CONST
;
7525 vset(&s
->type
, r
, s
->c
);
7526 /* if forward reference, we must point to s */
7527 if (vtop
->r
& VT_SYM
) {
7534 /* post operations */
7536 if (tok
== TOK_INC
|| tok
== TOK_DEC
) {
7539 } else if (tok
== '.' || tok
== TOK_ARROW
) {
7541 if (tok
== TOK_ARROW
)
7546 /* expect pointer on structure */
7547 if ((vtop
->type
.t
& VT_BTYPE
) != VT_STRUCT
)
7548 expect("struct or union");
7552 while ((s
= s
->next
) != NULL
) {
7557 error("field not found");
7558 /* add field offset to pointer */
7559 vtop
->type
= char_pointer_type
; /* change type to 'char *' */
7562 /* change type to field type, and set to lvalue */
7563 vtop
->type
= s
->type
;
7564 /* an array is never an lvalue */
7565 if (!(vtop
->type
.t
& VT_ARRAY
)) {
7566 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7567 /* if bound checking, the referenced pointer must be checked */
7568 if (do_bounds_check
)
7569 vtop
->r
|= VT_MUSTBOUND
;
7572 } else if (tok
== '[') {
7578 } else if (tok
== '(') {
7584 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
) {
7585 /* pointer test (no array accepted) */
7586 if ((vtop
->type
.t
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
7587 vtop
->type
= *pointed_type(&vtop
->type
);
7588 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
)
7592 expect("function pointer");
7595 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
7597 /* get return type */
7600 sa
= s
->next
; /* first parameter */
7602 /* compute first implicit argument if a structure is returned */
7603 if ((s
->type
.t
& VT_BTYPE
) == VT_STRUCT
) {
7604 /* get some space for the returned structure */
7605 size
= type_size(&s
->type
, &align
);
7606 loc
= (loc
- size
) & -align
;
7608 ret
.r
= VT_LOCAL
| VT_LVAL
;
7609 /* pass it as 'int' to avoid structure arg passing
7611 vseti(VT_LOCAL
, loc
);
7617 /* return in register */
7618 if (is_float(ret
.type
.t
)) {
7621 if ((ret
.type
.t
& VT_BTYPE
) == VT_LLONG
)
7630 gfunc_param_typed(s
, sa
);
7640 error("too few arguments to function");
7642 if (!nocode_wanted
) {
7643 gfunc_call(nb_args
);
7645 vtop
-= (nb_args
+ 1);
7648 vsetc(&ret
.type
, ret
.r
, &ret
.c
);
7656 static void uneq(void)
7662 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
7663 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
7664 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
7679 static void expr_prod(void)
7684 while (tok
== '*' || tok
== '/' || tok
== '%') {
7692 static void expr_sum(void)
7697 while (tok
== '+' || tok
== '-') {
7705 static void expr_shift(void)
7710 while (tok
== TOK_SHL
|| tok
== TOK_SAR
) {
7718 static void expr_cmp(void)
7723 while ((tok
>= TOK_ULE
&& tok
<= TOK_GT
) ||
7724 tok
== TOK_ULT
|| tok
== TOK_UGE
) {
7732 static void expr_cmpeq(void)
7737 while (tok
== TOK_EQ
|| tok
== TOK_NE
) {
7745 static void expr_and(void)
7748 while (tok
== '&') {
7755 static void expr_xor(void)
7758 while (tok
== '^') {
7765 static void expr_or(void)
7768 while (tok
== '|') {
7775 /* XXX: fix this mess */
7776 static void expr_land_const(void)
7779 while (tok
== TOK_LAND
) {
7786 /* XXX: fix this mess */
7787 static void expr_lor_const(void)
7790 while (tok
== TOK_LOR
) {
7797 /* only used if non constant */
7798 static void expr_land(void)
7803 if (tok
== TOK_LAND
) {
7808 if (tok
!= TOK_LAND
) {
7818 static void expr_lor(void)
7823 if (tok
== TOK_LOR
) {
7828 if (tok
!= TOK_LOR
) {
7838 /* XXX: better constant handling */
7839 static void expr_eq(void)
7841 int tt
, u
, r1
, r2
, rc
, t1
, t2
, bt1
, bt2
;
7843 CType type
, type1
, type2
;
7852 if (tok
== ':' && gnu_ext
) {
7868 if (vtop
!= vstack
) {
7869 /* needed to avoid having different registers saved in
7871 if (is_float(vtop
->type
.t
))
7878 if (tok
== ':' && gnu_ext
) {
7886 sv
= *vtop
; /* save value to handle it later */
7887 vtop
--; /* no vpop so that FP stack is not flushed */
7895 bt1
= t1
& VT_BTYPE
;
7897 bt2
= t2
& VT_BTYPE
;
7898 /* cast operands to correct type according to ISOC rules */
7899 if (is_float(bt1
) || is_float(bt2
)) {
7900 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
7901 type
.t
= VT_LDOUBLE
;
7902 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
7907 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
7908 /* cast to biggest op */
7910 /* convert to unsigned if it does not fit in a long long */
7911 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
7912 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
7913 type
.t
|= VT_UNSIGNED
;
7914 } else if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
7915 /* XXX: test pointer compatibility */
7917 } else if (bt1
== VT_FUNC
|| bt2
== VT_FUNC
) {
7918 /* XXX: test function pointer compatibility */
7920 } else if (bt1
== VT_STRUCT
|| bt2
== VT_STRUCT
) {
7921 /* XXX: test structure compatibility */
7923 } else if (bt1
== VT_VOID
|| bt2
== VT_VOID
) {
7924 /* NOTE: as an extension, we accept void on only one side */
7927 /* integer operations */
7929 /* convert to unsigned if it does not fit in an integer */
7930 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
7931 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
7932 type
.t
|= VT_UNSIGNED
;
7935 /* now we convert second operand */
7937 if (VT_STRUCT
== (vtop
->type
.t
& VT_BTYPE
))
7940 if (is_float(type
.t
)) {
7942 } else if ((type
.t
& VT_BTYPE
) == VT_LLONG
) {
7943 /* for long longs, we use fixed registers to avoid having
7944 to handle a complicated move */
7949 /* this is horrible, but we must also convert first
7953 /* put again first value and cast it */
7956 if (VT_STRUCT
== (vtop
->type
.t
& VT_BTYPE
))
7966 static void gexpr(void)
7977 /* parse an expression and return its type without any side effect. */
7978 static void expr_type(CType
*type
)
7980 int saved_nocode_wanted
;
7982 saved_nocode_wanted
= nocode_wanted
;
7987 nocode_wanted
= saved_nocode_wanted
;
7990 /* parse a unary expression and return its type without any side
7992 static void unary_type(CType
*type
)
8004 /* parse a constant expression and return value in vtop. */
8005 static void expr_const1(void)
8014 /* parse an integer constant and return its value. */
8015 static int expr_const(void)
8019 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
8020 expect("constant expression");
8026 /* return the label token if current token is a label, otherwise
8028 static int is_label(void)
8032 /* fast test first */
8033 if (tok
< TOK_UIDENT
)
8035 /* no need to save tokc because tok is an identifier */
8042 unget_tok(last_tok
);
8047 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
8048 int case_reg
, int is_expr
)
8053 /* generate line number info */
8055 (last_line_num
!= file
->line_num
|| last_ind
!= ind
)) {
8056 put_stabn(N_SLINE
, 0, file
->line_num
, ind
- func_ind
);
8058 last_line_num
= file
->line_num
;
8062 /* default return value is (void) */
8064 vtop
->type
.t
= VT_VOID
;
8067 if (tok
== TOK_IF
) {
8074 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
8076 if (c
== TOK_ELSE
) {
8080 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
8081 gsym(d
); /* patch else jmp */
8084 } else if (tok
== TOK_WHILE
) {
8092 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8096 } else if (tok
== '{') {
8100 /* record local declaration stack position */
8102 llabel
= local_label_stack
;
8103 /* handle local labels declarations */
8104 if (tok
== TOK_LABEL
) {
8107 if (tok
< TOK_UIDENT
)
8108 expect("label identifier");
8109 label_push(&local_label_stack
, tok
, LABEL_DECLARED
);
8119 while (tok
!= '}') {
8124 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
8127 /* pop locally defined labels */
8128 label_pop(&local_label_stack
, llabel
);
8129 /* pop locally defined symbols */
8130 sym_pop(&local_stack
, s
);
8132 } else if (tok
== TOK_RETURN
) {
8136 gen_assign_cast(&func_vt
);
8137 if ((func_vt
.t
& VT_BTYPE
) == VT_STRUCT
) {
8139 /* if returning structure, must copy it to implicit
8140 first pointer arg location */
8143 size
= type_size(&func_vt
,&align
);
8146 if((vtop
->r
!= (VT_LOCAL
| VT_LVAL
) || (vtop
->c
.i
& 3))
8150 loc
= (loc
- size
) & -4;
8153 vset(&type
, VT_LOCAL
| VT_LVAL
, addr
);
8156 vset(&int_type
, VT_LOCAL
| VT_LVAL
, addr
);
8158 vtop
->type
= int_type
;
8164 vset(&type
, VT_LOCAL
| VT_LVAL
, func_vc
);
8167 /* copy structure value to pointer */
8172 } else if (is_float(func_vt
.t
)) {
8177 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
8180 rsym
= gjmp(rsym
); /* jmp */
8181 } else if (tok
== TOK_BREAK
) {
8184 error("cannot break");
8185 *bsym
= gjmp(*bsym
);
8188 } else if (tok
== TOK_CONTINUE
) {
8191 error("cannot continue");
8192 *csym
= gjmp(*csym
);
8195 } else if (tok
== TOK_FOR
) {
8222 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8227 if (tok
== TOK_DO
) {
8232 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8243 if (tok
== TOK_SWITCH
) {
8247 /* XXX: other types than integer */
8248 case_reg
= gv(RC_INT
);
8252 b
= gjmp(0); /* jump to first case */
8254 block(&a
, csym
, &b
, &c
, case_reg
, 0);
8255 /* if no default, jmp after switch */
8263 if (tok
== TOK_CASE
) {
8270 if (gnu_ext
&& tok
== TOK_DOTS
) {
8274 warning("empty case range");
8276 /* since a case is like a label, we must skip it with a jmp */
8283 *case_sym
= gtst(1, 0);
8286 *case_sym
= gtst(1, 0);
8290 *case_sym
= gtst(1, *case_sym
);
8295 goto block_after_label
;
8297 if (tok
== TOK_DEFAULT
) {
8303 error("too many 'default'");
8306 goto block_after_label
;
8308 if (tok
== TOK_GOTO
) {
8310 if (tok
== '*' && gnu_ext
) {
8314 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
8317 } else if (tok
>= TOK_UIDENT
) {
8318 s
= label_find(tok
);
8319 /* put forward definition if needed */
8321 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
8323 if (s
->r
== LABEL_DECLARED
)
8324 s
->r
= LABEL_FORWARD
;
8326 /* label already defined */
8327 if (s
->r
& LABEL_FORWARD
)
8328 s
->next
= (void *)gjmp((long)s
->next
);
8330 gjmp_addr((long)s
->next
);
8333 expect("label identifier");
8336 } else if (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
) {
8344 if (s
->r
== LABEL_DEFINED
)
8345 error("duplicate label '%s'", get_tok_str(s
->v
, NULL
));
8346 gsym((long)s
->next
);
8347 s
->r
= LABEL_DEFINED
;
8349 s
= label_push(&global_label_stack
, b
, LABEL_DEFINED
);
8351 s
->next
= (void *)ind
;
8352 /* we accept this, but it is a mistake */
8355 warning("deprecated use of label at end of compound statement");
8359 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
8362 /* expression case */
8377 /* t is the array or struct type. c is the array or struct
8378 address. cur_index/cur_field is the pointer to the current
8379 value. 'size_only' is true if only size info is needed (only used
8381 static void decl_designator(CType
*type
, Section
*sec
, unsigned long c
,
8382 int *cur_index
, Sym
**cur_field
,
8386 int notfirst
, index
, index_last
, align
, l
, nb_elems
, elem_size
;
8392 if (gnu_ext
&& (l
= is_label()) != 0)
8394 while (tok
== '[' || tok
== '.') {
8396 if (!(type
->t
& VT_ARRAY
))
8397 expect("array type");
8400 index
= expr_const();
8401 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
8402 expect("invalid index");
8403 if (tok
== TOK_DOTS
&& gnu_ext
) {
8405 index_last
= expr_const();
8406 if (index_last
< 0 ||
8407 (s
->c
>= 0 && index_last
>= s
->c
) ||
8409 expect("invalid index");
8415 *cur_index
= index_last
;
8416 type
= pointed_type(type
);
8417 elem_size
= type_size(type
, &align
);
8418 c
+= index
* elem_size
;
8419 /* NOTE: we only support ranges for last designator */
8420 nb_elems
= index_last
- index
+ 1;
8421 if (nb_elems
!= 1) {
8430 if ((type
->t
& VT_BTYPE
) != VT_STRUCT
)
8431 expect("struct/union type");
8444 /* XXX: fix this mess by using explicit storage field */
8446 type1
.t
|= (type
->t
& ~VT_TYPE
);
8460 if (type
->t
& VT_ARRAY
) {
8462 type
= pointed_type(type
);
8463 c
+= index
* type_size(type
, &align
);
8467 error("too many field init");
8468 /* XXX: fix this mess by using explicit storage field */
8470 type1
.t
|= (type
->t
& ~VT_TYPE
);
8475 decl_initializer(type
, sec
, c
, 0, size_only
);
8477 /* XXX: make it more general */
8478 if (!size_only
&& nb_elems
> 1) {
8479 unsigned long c_end
;
8484 error("range init not supported yet for dynamic storage");
8485 c_end
= c
+ nb_elems
* elem_size
;
8486 if (c_end
> sec
->data_allocated
)
8487 section_realloc(sec
, c_end
);
8488 src
= sec
->data
+ c
;
8490 for(i
= 1; i
< nb_elems
; i
++) {
8492 memcpy(dst
, src
, elem_size
);
8498 #define EXPR_CONST 1
8501 /* store a value or an expression directly in global data or in local array */
8502 static void init_putv(CType
*type
, Section
*sec
, unsigned long c
,
8503 int v
, int expr_type
)
8505 int saved_global_expr
, bt
, bit_pos
, bit_size
;
8507 unsigned long long bit_mask
;
8515 /* compound literals must be allocated globally in this case */
8516 saved_global_expr
= global_expr
;
8519 global_expr
= saved_global_expr
;
8520 /* NOTE: symbols are accepted */
8521 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) != VT_CONST
)
8522 error("initializer element is not constant");
8530 dtype
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
8533 /* XXX: not portable */
8534 /* XXX: generate error if incorrect relocation */
8535 gen_assign_cast(&dtype
);
8536 bt
= type
->t
& VT_BTYPE
;
8537 ptr
= sec
->data
+ c
;
8538 /* XXX: make code faster ? */
8539 if (!(type
->t
& VT_BITFIELD
)) {
8544 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
8545 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
8546 bit_mask
= (1LL << bit_size
) - 1;
8548 if ((vtop
->r
& VT_SYM
) &&
8554 (bt
== VT_INT
&& bit_size
!= 32)))
8555 error("initializer element is not computable at load time");
8558 *(char *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8561 *(short *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8564 *(double *)ptr
= vtop
->c
.d
;
8567 *(long double *)ptr
= vtop
->c
.ld
;
8570 *(long long *)ptr
|= (vtop
->c
.ll
& bit_mask
) << bit_pos
;
8573 if (vtop
->r
& VT_SYM
) {
8574 greloc(sec
, vtop
->sym
, c
, R_DATA_32
);
8576 *(int *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8581 vset(&dtype
, VT_LOCAL
|VT_LVAL
, c
);
8588 /* put zeros for variable based init */
8589 static void init_putz(CType
*t
, Section
*sec
, unsigned long c
, int size
)
8592 /* nothing to do because globals are already set to zero */
8594 vpush_global_sym(&func_old_type
, TOK_memset
);
8602 /* 't' contains the type and storage info. 'c' is the offset of the
8603 object in section 'sec'. If 'sec' is NULL, it means stack based
8604 allocation. 'first' is true if array '{' must be read (multi
8605 dimension implicit array init handling). 'size_only' is true if
8606 size only evaluation is wanted (only for arrays). */
8607 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
8608 int first
, int size_only
)
8610 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
8611 int size1
, align1
, expr_type
;
8615 if (type
->t
& VT_ARRAY
) {
8619 t1
= pointed_type(type
);
8620 size1
= type_size(t1
, &align1
);
8623 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
8629 /* only parse strings here if correct type (otherwise: handle
8630 them as ((w)char *) expressions */
8631 if ((tok
== TOK_LSTR
&&
8632 #ifdef TCC_TARGET_PE
8633 (t1
->t
& VT_BTYPE
) == VT_SHORT
&& (t1
->t
& VT_UNSIGNED
)) ||
8635 (t1
->t
& VT_BTYPE
) == VT_INT
) ||
8638 (t1
->t
& VT_BTYPE
) == VT_BYTE
)) {
8639 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8644 /* compute maximum number of chars wanted */
8646 cstr_len
= cstr
->size
;
8648 cstr_len
= cstr
->size
/ sizeof(nwchar_t
);
8651 if (n
>= 0 && nb
> (n
- array_length
))
8652 nb
= n
- array_length
;
8655 warning("initializer-string for array is too long");
8656 /* in order to go faster for common case (char
8657 string in global variable, we handle it
8659 if (sec
&& tok
== TOK_STR
&& size1
== 1) {
8660 memcpy(sec
->data
+ c
+ array_length
, cstr
->data
, nb
);
8664 ch
= ((unsigned char *)cstr
->data
)[i
];
8666 ch
= ((nwchar_t
*)cstr
->data
)[i
];
8667 init_putv(t1
, sec
, c
+ (array_length
+ i
) * size1
,
8675 /* only add trailing zero if enough storage (no
8676 warning in this case since it is standard) */
8677 if (n
< 0 || array_length
< n
) {
8679 init_putv(t1
, sec
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
8685 while (tok
!= '}') {
8686 decl_designator(type
, sec
, c
, &index
, NULL
, size_only
);
8687 if (n
>= 0 && index
>= n
)
8688 error("index too large");
8689 /* must put zero in holes (note that doing it that way
8690 ensures that it even works with designators) */
8691 if (!size_only
&& array_length
< index
) {
8692 init_putz(t1
, sec
, c
+ array_length
* size1
,
8693 (index
- array_length
) * size1
);
8696 if (index
> array_length
)
8697 array_length
= index
;
8698 /* special test for multi dimensional arrays (may not
8699 be strictly correct if designators are used at the
8701 if (index
>= n
&& no_oblock
)
8710 /* put zeros at the end */
8711 if (!size_only
&& n
>= 0 && array_length
< n
) {
8712 init_putz(t1
, sec
, c
+ array_length
* size1
,
8713 (n
- array_length
) * size1
);
8715 /* patch type size if needed */
8717 s
->c
= array_length
;
8718 } else if ((type
->t
& VT_BTYPE
) == VT_STRUCT
&&
8719 (sec
|| !first
|| tok
== '{')) {
8722 /* NOTE: the previous test is a specific case for automatic
8723 struct/union init */
8724 /* XXX: union needs only one init */
8726 /* XXX: this test is incorrect for local initializers
8727 beginning with ( without {. It would be much more difficult
8728 to do it correctly (ideally, the expression parser should
8729 be used in all cases) */
8735 while (tok
== '(') {
8739 if (!parse_btype(&type1
, &ad1
))
8741 type_decl(&type1
, &ad1
, &n
, TYPE_ABSTRACT
);
8743 if (!is_assignable_types(type
, &type1
))
8744 error("invalid type for cast");
8749 if (first
|| tok
== '{') {
8758 while (tok
!= '}') {
8759 decl_designator(type
, sec
, c
, NULL
, &f
, size_only
);
8761 if (!size_only
&& array_length
< index
) {
8762 init_putz(type
, sec
, c
+ array_length
,
8763 index
- array_length
);
8765 index
= index
+ type_size(&f
->type
, &align1
);
8766 if (index
> array_length
)
8767 array_length
= index
;
8769 if (no_oblock
&& f
== NULL
)
8775 /* put zeros at the end */
8776 if (!size_only
&& array_length
< n
) {
8777 init_putz(type
, sec
, c
+ array_length
,
8786 } else if (tok
== '{') {
8788 decl_initializer(type
, sec
, c
, first
, size_only
);
8790 } else if (size_only
) {
8791 /* just skip expression */
8793 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
8797 else if (tok
== ')')
8802 /* currently, we always use constant expression for globals
8803 (may change for scripting case) */
8804 expr_type
= EXPR_CONST
;
8806 expr_type
= EXPR_ANY
;
8807 init_putv(type
, sec
, c
, 0, expr_type
);
8811 /* parse an initializer for type 't' if 'has_init' is non zero, and
8812 allocate space in local or global data space ('r' is either
8813 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8814 variable 'v' of scope 'scope' is declared before initializers are
8815 parsed. If 'v' is zero, then a reference to the new object is put
8816 in the value stack. If 'has_init' is 2, a special parsing is done
8817 to handle string constants. */
8818 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
8819 int has_init
, int v
, int scope
)
8821 int size
, align
, addr
, data_offset
;
8823 ParseState saved_parse_state
;
8824 TokenString init_str
;
8827 size
= type_size(type
, &align
);
8828 /* If unknown size, we must evaluate it before
8829 evaluating initializers because
8830 initializers can generate global data too
8831 (e.g. string pointers or ISOC99 compound
8832 literals). It also simplifies local
8833 initializers handling */
8834 tok_str_new(&init_str
);
8837 error("unknown type size");
8838 /* get all init string */
8839 if (has_init
== 2) {
8840 /* only get strings */
8841 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8842 tok_str_add_tok(&init_str
);
8847 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
8849 error("unexpected end of file in initializer");
8850 tok_str_add_tok(&init_str
);
8853 else if (tok
== '}') {
8861 tok_str_add(&init_str
, -1);
8862 tok_str_add(&init_str
, 0);
8865 save_parse_state(&saved_parse_state
);
8867 macro_ptr
= init_str
.str
;
8869 decl_initializer(type
, NULL
, 0, 1, 1);
8870 /* prepare second initializer parsing */
8871 macro_ptr
= init_str
.str
;
8874 /* if still unknown size, error */
8875 size
= type_size(type
, &align
);
8877 error("unknown type size");
8879 /* take into account specified alignment if bigger */
8881 if (ad
->aligned
> align
)
8882 align
= ad
->aligned
;
8883 } else if (ad
->packed
) {
8886 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
8888 if (do_bounds_check
&& (type
->t
& VT_ARRAY
))
8890 loc
= (loc
- size
) & -align
;
8892 /* handles bounds */
8893 /* XXX: currently, since we do only one pass, we cannot track
8894 '&' operators, so we add only arrays */
8895 if (do_bounds_check
&& (type
->t
& VT_ARRAY
)) {
8896 unsigned long *bounds_ptr
;
8897 /* add padding between regions */
8899 /* then add local bound info */
8900 bounds_ptr
= section_ptr_add(lbounds_section
, 2 * sizeof(unsigned long));
8901 bounds_ptr
[0] = addr
;
8902 bounds_ptr
[1] = size
;
8905 /* local variable */
8906 sym_push(v
, type
, r
, addr
);
8908 /* push local reference */
8909 vset(type
, r
, addr
);
8915 if (v
&& scope
== VT_CONST
) {
8916 /* see if the symbol was already defined */
8919 if (!is_compatible_types(&sym
->type
, type
))
8920 error("incompatible types for redefinition of '%s'",
8921 get_tok_str(v
, NULL
));
8922 if (sym
->type
.t
& VT_EXTERN
) {
8923 /* if the variable is extern, it was not allocated */
8924 sym
->type
.t
&= ~VT_EXTERN
;
8925 /* set array size if it was ommited in extern
8927 if ((sym
->type
.t
& VT_ARRAY
) &&
8928 sym
->type
.ref
->c
< 0 &&
8930 sym
->type
.ref
->c
= type
->ref
->c
;
8932 /* we accept several definitions of the same
8933 global variable. this is tricky, because we
8934 must play with the SHN_COMMON type of the symbol */
8935 /* XXX: should check if the variable was already
8936 initialized. It is incorrect to initialized it
8938 /* no init data, we won't add more to the symbol */
8945 /* allocate symbol in corresponding section */
8950 else if (tcc_state
->nocommon
)
8954 data_offset
= sec
->data_offset
;
8955 data_offset
= (data_offset
+ align
- 1) & -align
;
8957 /* very important to increment global pointer at this time
8958 because initializers themselves can create new initializers */
8959 data_offset
+= size
;
8960 /* add padding if bound check */
8961 if (do_bounds_check
)
8963 sec
->data_offset
= data_offset
;
8964 /* allocate section space to put the data */
8965 if (sec
->sh_type
!= SHT_NOBITS
&&
8966 data_offset
> sec
->data_allocated
)
8967 section_realloc(sec
, data_offset
);
8968 /* align section if needed */
8969 if (align
> sec
->sh_addralign
)
8970 sec
->sh_addralign
= align
;
8972 addr
= 0; /* avoid warning */
8976 if (scope
!= VT_CONST
|| !sym
) {
8977 sym
= sym_push(v
, type
, r
| VT_SYM
, 0);
8979 /* update symbol definition */
8981 put_extern_sym(sym
, sec
, addr
, size
);
8984 /* put a common area */
8985 put_extern_sym(sym
, NULL
, align
, size
);
8986 /* XXX: find a nicer way */
8987 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
8988 esym
->st_shndx
= SHN_COMMON
;
8993 /* push global reference */
8994 sym
= get_sym_ref(type
, sec
, addr
, size
);
8996 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
9000 /* handles bounds now because the symbol must be defined
9001 before for the relocation */
9002 if (do_bounds_check
) {
9003 unsigned long *bounds_ptr
;
9005 greloc(bounds_section
, sym
, bounds_section
->data_offset
, R_DATA_32
);
9006 /* then add global bound info */
9007 bounds_ptr
= section_ptr_add(bounds_section
, 2 * sizeof(long));
9008 bounds_ptr
[0] = 0; /* relocated */
9009 bounds_ptr
[1] = size
;
9013 decl_initializer(type
, sec
, addr
, 1, 0);
9014 /* restore parse state if needed */
9016 tok_str_free(init_str
.str
);
9017 restore_parse_state(&saved_parse_state
);
9023 void put_func_debug(Sym
*sym
)
9028 /* XXX: we put here a dummy type */
9029 snprintf(buf
, sizeof(buf
), "%s:%c1",
9030 funcname
, sym
->type
.t
& VT_STATIC
? 'f' : 'F');
9031 put_stabs_r(buf
, N_FUN
, 0, file
->line_num
, 0,
9032 cur_text_section
, sym
->c
);
9037 /* parse an old style function declaration list */
9038 /* XXX: check multiple parameter */
9039 static void func_decl_list(Sym
*func_sym
)
9046 /* parse each declaration */
9047 while (tok
!= '{' && tok
!= ';' && tok
!= ',' && tok
!= TOK_EOF
) {
9048 if (!parse_btype(&btype
, &ad
))
9049 expect("declaration list");
9050 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
9051 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
9053 /* we accept no variable after */
9057 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
9058 /* find parameter in function parameter list */
9061 if ((s
->v
& ~SYM_FIELD
) == v
)
9065 error("declaration for parameter '%s' but no such parameter",
9066 get_tok_str(v
, NULL
));
9068 /* check that no storage specifier except 'register' was given */
9069 if (type
.t
& VT_STORAGE
)
9070 error("storage class specified for '%s'", get_tok_str(v
, NULL
));
9071 convert_parameter_type(&type
);
9072 /* we can add the type (NOTE: it could be local to the function) */
9074 /* accept other parameters */
9085 /* parse a function defined by symbol 'sym' and generate its code in
9086 'cur_text_section' */
9087 static void gen_function(Sym
*sym
)
9089 int saved_nocode_wanted
= nocode_wanted
;
9091 ind
= cur_text_section
->data_offset
;
9092 /* NOTE: we patch the symbol size later */
9093 put_extern_sym(sym
, cur_text_section
, ind
, 0);
9094 funcname
= get_tok_str(sym
->v
, NULL
);
9096 /* put debug symbol */
9098 put_func_debug(sym
);
9099 /* push a dummy symbol to enable local sym storage */
9100 sym_push2(&local_stack
, SYM_FIELD
, 0, 0);
9101 gfunc_prolog(&sym
->type
);
9103 block(NULL
, NULL
, NULL
, NULL
, 0, 0);
9106 cur_text_section
->data_offset
= ind
;
9107 label_pop(&global_label_stack
, NULL
);
9108 sym_pop(&local_stack
, NULL
); /* reset local stack */
9109 /* end of function */
9110 /* patch symbol size */
9111 ((Elf32_Sym
*)symtab_section
->data
)[sym
->c
].st_size
=
9114 put_stabn(N_FUN
, 0, 0, ind
- func_ind
);
9116 funcname
= ""; /* for safety */
9117 func_vt
.t
= VT_VOID
; /* for safety */
9118 ind
= 0; /* for safety */
9119 nocode_wanted
= saved_nocode_wanted
;
9122 static void gen_inline_functions(void)
9126 int *str
, inline_generated
;
9128 /* iterate while inline function are referenced */
9130 inline_generated
= 0;
9131 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
9133 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
9134 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
9135 (VT_STATIC
| VT_INLINE
) &&
9137 /* the function was used: generate its code and
9138 convert it to a normal function */
9139 str
= (int *)sym
->r
;
9140 sym
->r
= VT_SYM
| VT_CONST
;
9141 type
->t
&= ~VT_INLINE
;
9145 cur_text_section
= text_section
;
9147 macro_ptr
= NULL
; /* fail safe */
9150 inline_generated
= 1;
9153 if (!inline_generated
)
9157 /* free all remaining inline function tokens */
9158 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
9160 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
9161 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
9162 (VT_STATIC
| VT_INLINE
)) {
9163 str
= (int *)sym
->r
;
9165 sym
->r
= 0; /* fail safe */
9170 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9171 static void decl(int l
)
9179 if (!parse_btype(&btype
, &ad
)) {
9180 /* skip redundant ';' */
9181 /* XXX: find more elegant solution */
9186 if (l
== VT_CONST
&&
9187 (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
)) {
9188 /* global asm block */
9192 /* special test for old K&R protos without explicit int
9193 type. Only accepted when defining global data */
9194 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
9198 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
9199 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
9201 /* we accept no variable after */
9205 while (1) { /* iterate thru each declaration */
9207 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
9211 type_to_str(buf
, sizeof(buf
), &type
, get_tok_str(v
, NULL
));
9212 printf("type = '%s'\n", buf
);
9215 if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9216 /* if old style function prototype, we accept a
9219 if (sym
->c
== FUNC_OLD
)
9220 func_decl_list(sym
);
9225 error("cannot use local functions");
9226 if ((type
.t
& VT_BTYPE
) != VT_FUNC
)
9227 expect("function definition");
9229 /* reject abstract declarators in function definition */
9231 while ((sym
= sym
->next
) != NULL
)
9232 if (!(sym
->v
& ~SYM_FIELD
))
9233 expect("identifier");
9235 /* XXX: cannot do better now: convert extern line to static inline */
9236 if ((type
.t
& (VT_EXTERN
| VT_INLINE
)) == (VT_EXTERN
| VT_INLINE
))
9237 type
.t
= (type
.t
& ~VT_EXTERN
) | VT_STATIC
;
9241 if ((sym
->type
.t
& VT_BTYPE
) != VT_FUNC
)
9243 /* specific case: if not func_call defined, we put
9244 the one of the prototype */
9245 /* XXX: should have default value */
9246 if (sym
->type
.ref
->r
!= FUNC_CDECL
&&
9247 type
.ref
->r
== FUNC_CDECL
)
9248 type
.ref
->r
= sym
->type
.ref
->r
;
9249 if (!is_compatible_types(&sym
->type
, &type
)) {
9251 error("incompatible types for redefinition of '%s'",
9252 get_tok_str(v
, NULL
));
9254 /* if symbol is already defined, then put complete type */
9257 /* put function symbol */
9258 sym
= global_identifier_push(v
, type
.t
, 0);
9259 sym
->type
.ref
= type
.ref
;
9262 /* static inline functions are just recorded as a kind
9263 of macro. Their code will be emitted at the end of
9264 the compilation unit only if they are used */
9265 if ((type
.t
& (VT_INLINE
| VT_STATIC
)) ==
9266 (VT_INLINE
| VT_STATIC
)) {
9267 TokenString func_str
;
9270 tok_str_new(&func_str
);
9276 error("unexpected end of file");
9277 tok_str_add_tok(&func_str
);
9282 } else if (t
== '}') {
9284 if (block_level
== 0)
9288 tok_str_add(&func_str
, -1);
9289 tok_str_add(&func_str
, 0);
9290 sym
->r
= (int)func_str
.str
;
9292 /* compute text section */
9293 cur_text_section
= ad
.section
;
9294 if (!cur_text_section
)
9295 cur_text_section
= text_section
;
9296 sym
->r
= VT_SYM
| VT_CONST
;
9298 #ifdef TCC_TARGET_PE
9300 ((Elf32_Sym
*)symtab_section
->data
)[sym
->c
].st_other
|= 1;
9306 if (btype
.t
& VT_TYPEDEF
) {
9307 /* save typedefed type */
9308 /* XXX: test storage specifiers ? */
9309 sym
= sym_push(v
, &type
, 0, 0);
9310 sym
->type
.t
|= VT_TYPEDEF
;
9311 } else if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9312 /* external function definition */
9313 /* specific case for func_call attribute */
9315 type
.ref
->r
= ad
.func_call
;
9316 external_sym(v
, &type
, 0);
9318 /* not lvalue if array */
9320 if (!(type
.t
& VT_ARRAY
))
9321 r
|= lvalue_type(type
.t
);
9322 has_init
= (tok
== '=');
9323 if ((btype
.t
& VT_EXTERN
) ||
9324 ((type
.t
& VT_ARRAY
) && (type
.t
& VT_STATIC
) &&
9325 !has_init
&& l
== VT_CONST
&& type
.ref
->c
< 0)) {
9326 /* external variable */
9327 /* NOTE: as GCC, uninitialized global static
9328 arrays of null size are considered as
9330 external_sym(v
, &type
, r
);
9332 type
.t
|= (btype
.t
& VT_STATIC
); /* Retain "static". */
9333 if (type
.t
& VT_STATIC
)
9339 decl_initializer_alloc(&type
, &ad
, r
,
9353 /* better than nothing, but needs extension to handle '-E' option
9355 static void preprocess_init(TCCState
*s1
)
9357 s1
->include_stack_ptr
= s1
->include_stack
;
9358 /* XXX: move that before to avoid having to initialize
9359 file->ifdef_stack_ptr ? */
9360 s1
->ifdef_stack_ptr
= s1
->ifdef_stack
;
9361 file
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
9363 /* XXX: not ANSI compliant: bound checking says error */
9365 s1
->pack_stack
[0] = 0;
9366 s1
->pack_stack_ptr
= s1
->pack_stack
;
9369 /* compile the C file opened in 'file'. Return non zero if errors. */
9370 static int tcc_compile(TCCState
*s1
)
9374 volatile int section_sym
;
9377 printf("%s: **** new file\n", file
->filename
);
9379 preprocess_init(s1
);
9382 anon_sym
= SYM_FIRST_ANOM
;
9384 /* file info: full path + filename */
9385 section_sym
= 0; /* avoid warning */
9387 section_sym
= put_elf_sym(symtab_section
, 0, 0,
9388 ELF32_ST_INFO(STB_LOCAL
, STT_SECTION
), 0,
9389 text_section
->sh_num
, NULL
);
9390 getcwd(buf
, sizeof(buf
));
9391 pstrcat(buf
, sizeof(buf
), "/");
9392 put_stabs_r(buf
, N_SO
, 0, 0,
9393 text_section
->data_offset
, text_section
, section_sym
);
9394 put_stabs_r(file
->filename
, N_SO
, 0, 0,
9395 text_section
->data_offset
, text_section
, section_sym
);
9397 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9398 symbols can be safely used */
9399 put_elf_sym(symtab_section
, 0, 0,
9400 ELF32_ST_INFO(STB_LOCAL
, STT_FILE
), 0,
9401 SHN_ABS
, file
->filename
);
9403 /* define some often used types */
9404 int_type
.t
= VT_INT
;
9406 char_pointer_type
.t
= VT_BYTE
;
9407 mk_pointer(&char_pointer_type
);
9409 func_old_type
.t
= VT_FUNC
;
9410 func_old_type
.ref
= sym_push(SYM_FIELD
, &int_type
, FUNC_CDECL
, FUNC_OLD
);
9412 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
9413 float_type
.t
= VT_FLOAT
;
9414 double_type
.t
= VT_DOUBLE
;
9416 func_float_type
.t
= VT_FUNC
;
9417 func_float_type
.ref
= sym_push(SYM_FIELD
, &float_type
, FUNC_CDECL
, FUNC_OLD
);
9418 func_double_type
.t
= VT_FUNC
;
9419 func_double_type
.ref
= sym_push(SYM_FIELD
, &double_type
, FUNC_CDECL
, FUNC_OLD
);
9423 /* define 'void *alloca(unsigned int)' builtin function */
9428 sym
= sym_push(p
, mk_pointer(VT_VOID
), FUNC_CDECL
, FUNC_NEW
);
9429 s1
= sym_push(SYM_FIELD
, VT_UNSIGNED
| VT_INT
, 0, 0);
9432 sym_push(TOK_alloca
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), VT_CONST
, 0);
9436 define_start
= define_stack
;
9439 if (setjmp(s1
->error_jmp_buf
) == 0) {
9441 s1
->error_set_jmp_enabled
= 1;
9443 ch
= file
->buf_ptr
[0];
9444 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
9445 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
;
9449 expect("declaration");
9451 /* end of translation unit info */
9453 put_stabs_r(NULL
, N_SO
, 0, 0,
9454 text_section
->data_offset
, text_section
, section_sym
);
9457 s1
->error_set_jmp_enabled
= 0;
9459 /* reset define stack, but leave -Dsymbols (may be incorrect if
9460 they are undefined) */
9461 free_defines(define_start
);
9463 gen_inline_functions();
9465 sym_pop(&global_stack
, NULL
);
9467 return s1
->nb_errors
!= 0 ? -1 : 0;
9470 /* Preprocess the current file */
9471 /* XXX: add line and file infos, add options to preserve spaces */
9472 static int tcc_preprocess(TCCState
*s1
)
9477 preprocess_init(s1
);
9479 define_start
= define_stack
;
9481 ch
= file
->buf_ptr
[0];
9482 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
9483 parse_flags
= PARSE_FLAG_ASM_COMMENTS
| PARSE_FLAG_PREPROCESS
|
9484 PARSE_FLAG_LINEFEED
;
9488 if (tok
== TOK_EOF
) {
9490 } else if (tok
== TOK_LINEFEED
) {
9494 fputc(' ', s1
->outfile
);
9497 fputs(get_tok_str(tok
, &tokc
), s1
->outfile
);
9500 free_defines(define_start
);
9505 int tcc_compile_string(TCCState
*s
, const char *str
)
9507 BufferedFile bf1
, *bf
= &bf1
;
9511 /* init file structure */
9513 /* XXX: avoid copying */
9515 buf
= tcc_malloc(len
+ 1);
9518 memcpy(buf
, str
, len
);
9521 bf
->buf_end
= buf
+ len
;
9522 pstrcpy(bf
->filename
, sizeof(bf
->filename
), "<string>");
9526 ret
= tcc_compile(s
);
9530 /* currently, no need to close */
9535 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9536 void tcc_define_symbol(TCCState
*s1
, const char *sym
, const char *value
)
9538 BufferedFile bf1
, *bf
= &bf1
;
9540 pstrcpy(bf
->buffer
, IO_BUF_SIZE
, sym
);
9541 pstrcat(bf
->buffer
, IO_BUF_SIZE
, " ");
9545 pstrcat(bf
->buffer
, IO_BUF_SIZE
, value
);
9547 /* init file structure */
9549 bf
->buf_ptr
= bf
->buffer
;
9550 bf
->buf_end
= bf
->buffer
+ strlen(bf
->buffer
);
9551 *bf
->buf_end
= CH_EOB
;
9552 bf
->filename
[0] = '\0';
9556 s1
->include_stack_ptr
= s1
->include_stack
;
9558 /* parse with define parser */
9559 ch
= file
->buf_ptr
[0];
9565 /* undefine a preprocessor symbol */
9566 void tcc_undefine_symbol(TCCState
*s1
, const char *sym
)
9570 ts
= tok_alloc(sym
, strlen(sym
));
9571 s
= define_find(ts
->tok
);
9572 /* undefine symbol by putting an invalid name */
9577 #ifdef CONFIG_TCC_ASM
9579 #ifdef TCC_TARGET_I386
9580 #include "i386-asm.c"
9585 static void asm_instr(void)
9587 error("inline asm() not supported");
9589 static void asm_global_instr(void)
9591 error("inline asm() not supported");
9597 #ifdef TCC_TARGET_COFF
9598 #include "tcccoff.c"
9601 #ifdef TCC_TARGET_PE
9605 /* print the position in the source file of PC value 'pc' by reading
9606 the stabs debug information */
9607 static void rt_printline(unsigned long wanted_pc
)
9609 Stab_Sym
*sym
, *sym_end
;
9610 char func_name
[128], last_func_name
[128];
9611 unsigned long func_addr
, last_pc
, pc
;
9612 const char *incl_files
[INCLUDE_STACK_SIZE
];
9613 int incl_index
, len
, last_line_num
, i
;
9614 const char *str
, *p
;
9616 fprintf(stderr
, "0x%08lx:", wanted_pc
);
9618 func_name
[0] = '\0';
9621 last_func_name
[0] = '\0';
9622 last_pc
= 0xffffffff;
9624 sym
= (Stab_Sym
*)stab_section
->data
+ 1;
9625 sym_end
= (Stab_Sym
*)(stab_section
->data
+ stab_section
->data_offset
);
9626 while (sym
< sym_end
) {
9627 switch(sym
->n_type
) {
9628 /* function start or end */
9630 if (sym
->n_strx
== 0) {
9631 /* we test if between last line and end of function */
9632 pc
= sym
->n_value
+ func_addr
;
9633 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
9635 func_name
[0] = '\0';
9638 str
= stabstr_section
->data
+ sym
->n_strx
;
9639 p
= strchr(str
, ':');
9641 pstrcpy(func_name
, sizeof(func_name
), str
);
9644 if (len
> sizeof(func_name
) - 1)
9645 len
= sizeof(func_name
) - 1;
9646 memcpy(func_name
, str
, len
);
9647 func_name
[len
] = '\0';
9649 func_addr
= sym
->n_value
;
9652 /* line number info */
9654 pc
= sym
->n_value
+ func_addr
;
9655 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
9658 last_line_num
= sym
->n_desc
;
9660 strcpy(last_func_name
, func_name
);
9664 str
= stabstr_section
->data
+ sym
->n_strx
;
9666 if (incl_index
< INCLUDE_STACK_SIZE
) {
9667 incl_files
[incl_index
++] = str
;
9675 if (sym
->n_strx
== 0) {
9676 incl_index
= 0; /* end of translation unit */
9678 str
= stabstr_section
->data
+ sym
->n_strx
;
9679 /* do not add path */
9681 if (len
> 0 && str
[len
- 1] != '/')
9689 /* second pass: we try symtab symbols (no line number info) */
9692 Elf32_Sym
*sym
, *sym_end
;
9695 sym_end
= (Elf32_Sym
*)(symtab_section
->data
+ symtab_section
->data_offset
);
9696 for(sym
= (Elf32_Sym
*)symtab_section
->data
+ 1;
9699 type
= ELF32_ST_TYPE(sym
->st_info
);
9700 if (type
== STT_FUNC
) {
9701 if (wanted_pc
>= sym
->st_value
&&
9702 wanted_pc
< sym
->st_value
+ sym
->st_size
) {
9703 pstrcpy(last_func_name
, sizeof(last_func_name
),
9704 strtab_section
->data
+ sym
->st_name
);
9710 /* did not find any info: */
9711 fprintf(stderr
, " ???\n");
9714 if (last_func_name
[0] != '\0') {
9715 fprintf(stderr
, " %s()", last_func_name
);
9717 if (incl_index
> 0) {
9718 fprintf(stderr
, " (%s:%d",
9719 incl_files
[incl_index
- 1], last_line_num
);
9720 for(i
= incl_index
- 2; i
>= 0; i
--)
9721 fprintf(stderr
, ", included from %s", incl_files
[i
]);
9722 fprintf(stderr
, ")");
9724 fprintf(stderr
, "\n");
9727 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
9731 /* fix for glibc 2.1 */
9737 /* return the PC at frame level 'level'. Return non zero if not found */
9738 static int rt_get_caller_pc(unsigned long *paddr
,
9739 ucontext_t
*uc
, int level
)
9745 #if defined(__FreeBSD__)
9746 *paddr
= uc
->uc_mcontext
.mc_eip
;
9747 #elif defined(__dietlibc__)
9748 *paddr
= uc
->uc_mcontext
.eip
;
9750 *paddr
= uc
->uc_mcontext
.gregs
[REG_EIP
];
9754 #if defined(__FreeBSD__)
9755 fp
= uc
->uc_mcontext
.mc_ebp
;
9756 #elif defined(__dietlibc__)
9757 fp
= uc
->uc_mcontext
.ebp
;
9759 fp
= uc
->uc_mcontext
.gregs
[REG_EBP
];
9761 for(i
=1;i
<level
;i
++) {
9762 /* XXX: check address validity with program info */
9763 if (fp
<= 0x1000 || fp
>= 0xc0000000)
9765 fp
= ((unsigned long *)fp
)[0];
9767 *paddr
= ((unsigned long *)fp
)[1];
9773 #warning add arch specific rt_get_caller_pc()
9775 static int rt_get_caller_pc(unsigned long *paddr
,
9776 ucontext_t
*uc
, int level
)
9782 /* emit a run time error at position 'pc' */
9783 void rt_error(ucontext_t
*uc
, const char *fmt
, ...)
9790 fprintf(stderr
, "Runtime error: ");
9791 vfprintf(stderr
, fmt
, ap
);
9792 fprintf(stderr
, "\n");
9793 for(i
=0;i
<num_callers
;i
++) {
9794 if (rt_get_caller_pc(&pc
, uc
, i
) < 0)
9797 fprintf(stderr
, "at ");
9799 fprintf(stderr
, "by ");
9806 /* signal handler for fatal errors */
9807 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
9809 ucontext_t
*uc
= puc
;
9813 switch(siginf
->si_code
) {
9816 rt_error(uc
, "division by zero");
9819 rt_error(uc
, "floating point exception");
9825 if (rt_bound_error_msg
&& *rt_bound_error_msg
)
9826 rt_error(uc
, *rt_bound_error_msg
);
9828 rt_error(uc
, "dereferencing invalid pointer");
9831 rt_error(uc
, "illegal instruction");
9834 rt_error(uc
, "abort() called");
9837 rt_error(uc
, "caught signal %d", signum
);
9844 /* do all relocations (needed before using tcc_get_symbol()) */
9845 int tcc_relocate(TCCState
*s1
)
9852 #ifdef TCC_TARGET_PE
9855 tcc_add_runtime(s1
);
9858 relocate_common_syms();
9860 tcc_add_linker_symbols(s1
);
9862 build_got_entries(s1
);
9864 /* compute relocation address : section are relocated in place. We
9865 also alloc the bss space */
9866 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9867 s
= s1
->sections
[i
];
9868 if (s
->sh_flags
& SHF_ALLOC
) {
9869 if (s
->sh_type
== SHT_NOBITS
)
9870 s
->data
= tcc_mallocz(s
->data_offset
);
9871 s
->sh_addr
= (unsigned long)s
->data
;
9875 relocate_syms(s1
, 1);
9877 if (s1
->nb_errors
!= 0)
9880 /* relocate each section */
9881 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9882 s
= s1
->sections
[i
];
9884 relocate_section(s1
, s
);
9887 /* mark executable sections as executable in memory */
9888 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9889 s
= s1
->sections
[i
];
9890 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_EXECINSTR
)) ==
9891 (SHF_ALLOC
| SHF_EXECINSTR
)) {
9894 unsigned long old_protect
;
9895 VirtualProtect(s
->data
, s
->data_offset
,
9896 PAGE_EXECUTE_READWRITE
, &old_protect
);
9900 unsigned long start
, end
;
9901 start
= (unsigned long)(s
->data
) & ~(PAGESIZE
- 1);
9902 end
= (unsigned long)(s
->data
+ s
->data_offset
);
9903 end
= (end
+ PAGESIZE
- 1) & ~(PAGESIZE
- 1);
9904 mprotect((void *)start
, end
- start
,
9905 PROT_READ
| PROT_WRITE
| PROT_EXEC
);
9913 /* launch the compiled program with the given arguments */
9914 int tcc_run(TCCState
*s1
, int argc
, char **argv
)
9916 int (*prog_main
)(int, char **);
9918 if (tcc_relocate(s1
) < 0)
9921 prog_main
= tcc_get_symbol_err(s1
, "main");
9924 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
9925 error("debug mode currently not available for Windows");
9927 struct sigaction sigact
;
9928 /* install TCC signal handlers to print debug info on fatal
9930 sigact
.sa_flags
= SA_SIGINFO
| SA_RESETHAND
;
9931 sigact
.sa_sigaction
= sig_error
;
9932 sigemptyset(&sigact
.sa_mask
);
9933 sigaction(SIGFPE
, &sigact
, NULL
);
9934 sigaction(SIGILL
, &sigact
, NULL
);
9935 sigaction(SIGSEGV
, &sigact
, NULL
);
9936 sigaction(SIGBUS
, &sigact
, NULL
);
9937 sigaction(SIGABRT
, &sigact
, NULL
);
9941 #ifdef CONFIG_TCC_BCHECK
9942 if (do_bounds_check
) {
9943 void (*bound_init
)(void);
9945 /* set error function */
9946 rt_bound_error_msg
= (void *)tcc_get_symbol_err(s1
,
9947 "__bound_error_msg");
9949 /* XXX: use .init section so that it also work in binary ? */
9950 bound_init
= (void *)tcc_get_symbol_err(s1
, "__bound_init");
9954 return (*prog_main
)(argc
, argv
);
9957 TCCState
*tcc_new(void)
9964 s
= tcc_mallocz(sizeof(TCCState
));
9968 s
->output_type
= TCC_OUTPUT_MEMORY
;
9970 /* init isid table */
9972 isidnum_table
[i
] = isid(i
) || isnum(i
);
9974 /* add all tokens */
9976 memset(hash_ident
, 0, TOK_HASH_SIZE
* sizeof(TokenSym
*));
9978 tok_ident
= TOK_IDENT
;
9987 ts
= tok_alloc(p
, r
- p
- 1);
9991 /* we add dummy defines for some special macros to speed up tests
9992 and to have working defined() */
9993 define_push(TOK___LINE__
, MACRO_OBJ
, NULL
, NULL
);
9994 define_push(TOK___FILE__
, MACRO_OBJ
, NULL
, NULL
);
9995 define_push(TOK___DATE__
, MACRO_OBJ
, NULL
, NULL
);
9996 define_push(TOK___TIME__
, MACRO_OBJ
, NULL
, NULL
);
9998 /* standard defines */
9999 tcc_define_symbol(s
, "__STDC__", NULL
);
10000 #if defined(TCC_TARGET_I386)
10001 tcc_define_symbol(s
, "__i386__", NULL
);
10003 #if defined(TCC_TARGET_ARM)
10004 tcc_define_symbol(s
, "__ARM_ARCH_4__", NULL
);
10005 tcc_define_symbol(s
, "__arm_elf__", NULL
);
10006 tcc_define_symbol(s
, "__arm_elf", NULL
);
10007 tcc_define_symbol(s
, "arm_elf", NULL
);
10008 tcc_define_symbol(s
, "__arm__", NULL
);
10009 tcc_define_symbol(s
, "__arm", NULL
);
10010 tcc_define_symbol(s
, "arm", NULL
);
10011 tcc_define_symbol(s
, "__APCS_32__", NULL
);
10014 tcc_define_symbol(s
, "__linux__", NULL
);
10015 tcc_define_symbol(s
, "linux", NULL
);
10017 /* tiny C specific defines */
10018 tcc_define_symbol(s
, "__TINYC__", NULL
);
10020 /* tiny C & gcc defines */
10021 tcc_define_symbol(s
, "__SIZE_TYPE__", "unsigned int");
10022 tcc_define_symbol(s
, "__PTRDIFF_TYPE__", "int");
10023 #ifdef TCC_TARGET_PE
10024 tcc_define_symbol(s
, "__WCHAR_TYPE__", "unsigned short");
10026 tcc_define_symbol(s
, "__WCHAR_TYPE__", "int");
10029 /* default library paths */
10030 #ifdef TCC_TARGET_PE
10033 snprintf(buf
, sizeof(buf
), "%s/lib", tcc_lib_path
);
10034 tcc_add_library_path(s
, buf
);
10037 tcc_add_library_path(s
, "/usr/local/lib");
10038 tcc_add_library_path(s
, "/usr/lib");
10039 tcc_add_library_path(s
, "/lib");
10042 /* no section zero */
10043 dynarray_add((void ***)&s
->sections
, &s
->nb_sections
, NULL
);
10045 /* create standard sections */
10046 text_section
= new_section(s
, ".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
10047 data_section
= new_section(s
, ".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
10048 bss_section
= new_section(s
, ".bss", SHT_NOBITS
, SHF_ALLOC
| SHF_WRITE
);
10050 /* symbols are always generated for linking stage */
10051 symtab_section
= new_symtab(s
, ".symtab", SHT_SYMTAB
, 0,
10053 ".hashtab", SHF_PRIVATE
);
10054 strtab_section
= symtab_section
->link
;
10056 /* private symbol table for dynamic symbols */
10057 s
->dynsymtab_section
= new_symtab(s
, ".dynsymtab", SHT_SYMTAB
, SHF_PRIVATE
,
10059 ".dynhashtab", SHF_PRIVATE
);
10060 s
->alacarte_link
= 1;
10062 #ifdef CHAR_IS_UNSIGNED
10063 s
->char_is_unsigned
= 1;
10065 #if defined(TCC_TARGET_PE) && 0
10066 /* XXX: currently the PE linker is not ready to support that */
10067 s
->leading_underscore
= 1;
10072 void tcc_delete(TCCState
*s1
)
10076 /* free -D defines */
10077 free_defines(NULL
);
10080 n
= tok_ident
- TOK_IDENT
;
10081 for(i
= 0; i
< n
; i
++)
10082 tcc_free(table_ident
[i
]);
10083 tcc_free(table_ident
);
10085 /* free all sections */
10087 free_section(symtab_section
->hash
);
10089 free_section(s1
->dynsymtab_section
->hash
);
10090 free_section(s1
->dynsymtab_section
->link
);
10091 free_section(s1
->dynsymtab_section
);
10093 for(i
= 1; i
< s1
->nb_sections
; i
++)
10094 free_section(s1
->sections
[i
]);
10095 tcc_free(s1
->sections
);
10097 /* free loaded dlls array */
10098 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++)
10099 tcc_free(s1
->loaded_dlls
[i
]);
10100 tcc_free(s1
->loaded_dlls
);
10102 /* library paths */
10103 for(i
= 0; i
< s1
->nb_library_paths
; i
++)
10104 tcc_free(s1
->library_paths
[i
]);
10105 tcc_free(s1
->library_paths
);
10107 /* cached includes */
10108 for(i
= 0; i
< s1
->nb_cached_includes
; i
++)
10109 tcc_free(s1
->cached_includes
[i
]);
10110 tcc_free(s1
->cached_includes
);
10112 for(i
= 0; i
< s1
->nb_include_paths
; i
++)
10113 tcc_free(s1
->include_paths
[i
]);
10114 tcc_free(s1
->include_paths
);
10116 for(i
= 0; i
< s1
->nb_sysinclude_paths
; i
++)
10117 tcc_free(s1
->sysinclude_paths
[i
]);
10118 tcc_free(s1
->sysinclude_paths
);
10123 int tcc_add_include_path(TCCState
*s1
, const char *pathname
)
10127 pathname1
= tcc_strdup(pathname
);
10128 dynarray_add((void ***)&s1
->include_paths
, &s1
->nb_include_paths
, pathname1
);
10132 int tcc_add_sysinclude_path(TCCState
*s1
, const char *pathname
)
10136 pathname1
= tcc_strdup(pathname
);
10137 dynarray_add((void ***)&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
, pathname1
);
10141 static int tcc_add_file_internal(TCCState
*s1
, const char *filename
, int flags
)
10143 const char *ext
, *filename1
;
10146 BufferedFile
*saved_file
;
10148 /* find source file type with extension */
10149 filename1
= strrchr(filename
, '/');
10153 filename1
= filename
;
10154 ext
= strrchr(filename1
, '.');
10158 /* open the file */
10160 file
= tcc_open(s1
, filename
);
10162 if (flags
& AFF_PRINT_ERROR
) {
10163 error_noabort("file '%s' not found", filename
);
10169 if (flags
& AFF_PREPROCESS
) {
10170 ret
= tcc_preprocess(s1
);
10171 } else if (!ext
|| !strcmp(ext
, "c")) {
10172 /* C file assumed */
10173 ret
= tcc_compile(s1
);
10175 #ifdef CONFIG_TCC_ASM
10176 if (!strcmp(ext
, "S")) {
10177 /* preprocessed assembler */
10178 ret
= tcc_assemble(s1
, 1);
10179 } else if (!strcmp(ext
, "s")) {
10180 /* non preprocessed assembler */
10181 ret
= tcc_assemble(s1
, 0);
10184 #ifdef TCC_TARGET_PE
10185 if (!strcmp(ext
, "def")) {
10186 ret
= pe_load_def_file(s1
, fdopen(file
->fd
, "rb"));
10191 /* assume executable format: auto guess file type */
10192 ret
= read(fd
, &ehdr
, sizeof(ehdr
));
10193 lseek(fd
, 0, SEEK_SET
);
10195 error_noabort("could not read header");
10197 } else if (ret
!= sizeof(ehdr
)) {
10198 goto try_load_script
;
10201 if (ehdr
.e_ident
[0] == ELFMAG0
&&
10202 ehdr
.e_ident
[1] == ELFMAG1
&&
10203 ehdr
.e_ident
[2] == ELFMAG2
&&
10204 ehdr
.e_ident
[3] == ELFMAG3
) {
10205 file
->line_num
= 0; /* do not display line number if error */
10206 if (ehdr
.e_type
== ET_REL
) {
10207 ret
= tcc_load_object_file(s1
, fd
, 0);
10208 } else if (ehdr
.e_type
== ET_DYN
) {
10209 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
10210 #ifdef TCC_TARGET_PE
10214 h
= dlopen(filename
, RTLD_GLOBAL
| RTLD_LAZY
);
10221 ret
= tcc_load_dll(s1
, fd
, filename
,
10222 (flags
& AFF_REFERENCED_DLL
) != 0);
10225 error_noabort("unrecognized ELF file");
10228 } else if (memcmp((char *)&ehdr
, ARMAG
, 8) == 0) {
10229 file
->line_num
= 0; /* do not display line number if error */
10230 ret
= tcc_load_archive(s1
, fd
);
10232 #ifdef TCC_TARGET_COFF
10233 if (*(uint16_t *)(&ehdr
) == COFF_C67_MAGIC
) {
10234 ret
= tcc_load_coff(s1
, fd
);
10238 /* as GNU ld, consider it is an ld script if not recognized */
10240 ret
= tcc_load_ldscript(s1
);
10242 error_noabort("unrecognized file type");
10257 int tcc_add_file(TCCState
*s
, const char *filename
)
10259 return tcc_add_file_internal(s
, filename
, AFF_PRINT_ERROR
);
10262 int tcc_add_library_path(TCCState
*s
, const char *pathname
)
10266 pathname1
= tcc_strdup(pathname
);
10267 dynarray_add((void ***)&s
->library_paths
, &s
->nb_library_paths
, pathname1
);
10271 /* find and load a dll. Return non zero if not found */
10272 /* XXX: add '-rpath' option support ? */
10273 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
)
10278 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
10279 snprintf(buf
, sizeof(buf
), "%s/%s",
10280 s
->library_paths
[i
], filename
);
10281 if (tcc_add_file_internal(s
, buf
, flags
) == 0)
10287 /* the library name is the same as the argument of the '-l' option */
10288 int tcc_add_library(TCCState
*s
, const char *libraryname
)
10293 /* first we look for the dynamic library if not static linking */
10294 if (!s
->static_link
) {
10295 #ifdef TCC_TARGET_PE
10296 snprintf(buf
, sizeof(buf
), "%s.def", libraryname
);
10298 snprintf(buf
, sizeof(buf
), "lib%s.so", libraryname
);
10300 if (tcc_add_dll(s
, buf
, 0) == 0)
10304 /* then we look for the static library */
10305 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
10306 snprintf(buf
, sizeof(buf
), "%s/lib%s.a",
10307 s
->library_paths
[i
], libraryname
);
10308 if (tcc_add_file_internal(s
, buf
, 0) == 0)
10314 int tcc_add_symbol(TCCState
*s
, const char *name
, unsigned long val
)
10316 add_elf_sym(symtab_section
, val
, 0,
10317 ELF32_ST_INFO(STB_GLOBAL
, STT_NOTYPE
), 0,
10322 int tcc_set_output_type(TCCState
*s
, int output_type
)
10324 s
->output_type
= output_type
;
10326 if (!s
->nostdinc
) {
10329 /* default include paths */
10330 /* XXX: reverse order needed if -isystem support */
10331 #ifndef TCC_TARGET_PE
10332 tcc_add_sysinclude_path(s
, "/usr/local/include");
10333 tcc_add_sysinclude_path(s
, "/usr/include");
10335 snprintf(buf
, sizeof(buf
), "%s/include", tcc_lib_path
);
10336 tcc_add_sysinclude_path(s
, buf
);
10337 #ifdef TCC_TARGET_PE
10338 snprintf(buf
, sizeof(buf
), "%s/include/winapi", tcc_lib_path
);
10339 tcc_add_sysinclude_path(s
, buf
);
10343 /* if bound checking, then add corresponding sections */
10344 #ifdef CONFIG_TCC_BCHECK
10345 if (do_bounds_check
) {
10346 /* define symbol */
10347 tcc_define_symbol(s
, "__BOUNDS_CHECKING_ON", NULL
);
10348 /* create bounds sections */
10349 bounds_section
= new_section(s
, ".bounds",
10350 SHT_PROGBITS
, SHF_ALLOC
);
10351 lbounds_section
= new_section(s
, ".lbounds",
10352 SHT_PROGBITS
, SHF_ALLOC
);
10356 if (s
->char_is_unsigned
) {
10357 tcc_define_symbol(s
, "__CHAR_UNSIGNED__", NULL
);
10360 /* add debug sections */
10363 stab_section
= new_section(s
, ".stab", SHT_PROGBITS
, 0);
10364 stab_section
->sh_entsize
= sizeof(Stab_Sym
);
10365 stabstr_section
= new_section(s
, ".stabstr", SHT_STRTAB
, 0);
10366 put_elf_str(stabstr_section
, "");
10367 stab_section
->link
= stabstr_section
;
10368 /* put first entry */
10369 put_stabs("", 0, 0, 0, 0);
10372 /* add libc crt1/crti objects */
10373 #ifndef TCC_TARGET_PE
10374 if ((output_type
== TCC_OUTPUT_EXE
|| output_type
== TCC_OUTPUT_DLL
) &&
10376 if (output_type
!= TCC_OUTPUT_DLL
)
10377 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crt1.o");
10378 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crti.o");
10384 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10385 #define FD_INVERT 0x0002 /* invert value before storing */
10387 typedef struct FlagDef
{
10393 static const FlagDef warning_defs
[] = {
10394 { offsetof(TCCState
, warn_unsupported
), 0, "unsupported" },
10395 { offsetof(TCCState
, warn_write_strings
), 0, "write-strings" },
10396 { offsetof(TCCState
, warn_error
), 0, "error" },
10397 { offsetof(TCCState
, warn_implicit_function_declaration
), WD_ALL
,
10398 "implicit-function-declaration" },
10401 static int set_flag(TCCState
*s
, const FlagDef
*flags
, int nb_flags
,
10402 const char *name
, int value
)
10409 if (r
[0] == 'n' && r
[1] == 'o' && r
[2] == '-') {
10413 for(i
= 0, p
= flags
; i
< nb_flags
; i
++, p
++) {
10414 if (!strcmp(r
, p
->name
))
10419 if (p
->flags
& FD_INVERT
)
10421 *(int *)((uint8_t *)s
+ p
->offset
) = value
;
10426 /* set/reset a warning */
10427 int tcc_set_warning(TCCState
*s
, const char *warning_name
, int value
)
10432 if (!strcmp(warning_name
, "all")) {
10433 for(i
= 0, p
= warning_defs
; i
< countof(warning_defs
); i
++, p
++) {
10434 if (p
->flags
& WD_ALL
)
10435 *(int *)((uint8_t *)s
+ p
->offset
) = 1;
10439 return set_flag(s
, warning_defs
, countof(warning_defs
),
10440 warning_name
, value
);
10444 static const FlagDef flag_defs
[] = {
10445 { offsetof(TCCState
, char_is_unsigned
), 0, "unsigned-char" },
10446 { offsetof(TCCState
, char_is_unsigned
), FD_INVERT
, "signed-char" },
10447 { offsetof(TCCState
, nocommon
), FD_INVERT
, "common" },
10448 { offsetof(TCCState
, leading_underscore
), 0, "leading-underscore" },
10451 /* set/reset a flag */
10452 int tcc_set_flag(TCCState
*s
, const char *flag_name
, int value
)
10454 return set_flag(s
, flag_defs
, countof(flag_defs
),
10458 /* extract the basename of a file */
10459 static char *tcc_basename(const char *name
)
10461 char *p
= strchr(name
, 0);
10472 #if !defined(LIBTCC)
10474 static int64_t getclock_us(void)
10479 return (tb
.time
* 1000LL + tb
.millitm
) * 1000LL;
10482 gettimeofday(&tv
, NULL
);
10483 return tv
.tv_sec
* 1000000LL + tv
.tv_usec
;
10489 printf("tcc version " TCC_VERSION
" - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10490 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10491 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10492 " [infile1 infile2...] [-run infile args...]\n"
10494 "General options:\n"
10495 " -v display current version\n"
10496 " -c compile only - generate an object file\n"
10497 " -o outfile set output filename\n"
10498 " -Bdir set tcc internal library path\n"
10499 " -bench output compilation statistics\n"
10500 " -run run compiled source\n"
10501 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10502 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10503 " -w disable all warnings\n"
10504 "Preprocessor options:\n"
10505 " -E preprocess only\n"
10506 " -Idir add include path 'dir'\n"
10507 " -Dsym[=val] define 'sym' with value 'val'\n"
10508 " -Usym undefine 'sym'\n"
10509 "Linker options:\n"
10510 " -Ldir add library path 'dir'\n"
10511 " -llib link with dynamic or static library 'lib'\n"
10512 " -shared generate a shared library\n"
10513 " -static static linking\n"
10514 " -rdynamic export all global symbols to dynamic linker\n"
10515 " -r relocatable output\n"
10516 "Debugger options:\n"
10517 " -g generate runtime debug info\n"
10518 #ifdef CONFIG_TCC_BCHECK
10519 " -b compile with built-in memory and bounds checker (implies -g)\n"
10521 " -bt N show N callers in stack traces\n"
10525 #define TCC_OPTION_HAS_ARG 0x0001
10526 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10528 typedef struct TCCOption
{
10556 TCC_OPTION_nostdinc
,
10557 TCC_OPTION_nostdlib
,
10558 TCC_OPTION_print_search_dirs
,
10559 TCC_OPTION_rdynamic
,
10567 static const TCCOption tcc_options
[] = {
10568 { "h", TCC_OPTION_HELP
, 0 },
10569 { "?", TCC_OPTION_HELP
, 0 },
10570 { "I", TCC_OPTION_I
, TCC_OPTION_HAS_ARG
},
10571 { "D", TCC_OPTION_D
, TCC_OPTION_HAS_ARG
},
10572 { "U", TCC_OPTION_U
, TCC_OPTION_HAS_ARG
},
10573 { "L", TCC_OPTION_L
, TCC_OPTION_HAS_ARG
},
10574 { "B", TCC_OPTION_B
, TCC_OPTION_HAS_ARG
},
10575 { "l", TCC_OPTION_l
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10576 { "bench", TCC_OPTION_bench
, 0 },
10577 { "bt", TCC_OPTION_bt
, TCC_OPTION_HAS_ARG
},
10578 #ifdef CONFIG_TCC_BCHECK
10579 { "b", TCC_OPTION_b
, 0 },
10581 { "g", TCC_OPTION_g
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10582 { "c", TCC_OPTION_c
, 0 },
10583 { "static", TCC_OPTION_static
, 0 },
10584 { "shared", TCC_OPTION_shared
, 0 },
10585 { "o", TCC_OPTION_o
, TCC_OPTION_HAS_ARG
},
10586 { "run", TCC_OPTION_run
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10587 { "rdynamic", TCC_OPTION_rdynamic
, 0 },
10588 { "r", TCC_OPTION_r
, 0 },
10589 { "Wl,", TCC_OPTION_Wl
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10590 { "W", TCC_OPTION_W
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10591 { "O", TCC_OPTION_O
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10592 { "m", TCC_OPTION_m
, TCC_OPTION_HAS_ARG
},
10593 { "f", TCC_OPTION_f
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10594 { "nostdinc", TCC_OPTION_nostdinc
, 0 },
10595 { "nostdlib", TCC_OPTION_nostdlib
, 0 },
10596 { "print-search-dirs", TCC_OPTION_print_search_dirs
, 0 },
10597 { "v", TCC_OPTION_v
, 0 },
10598 { "w", TCC_OPTION_w
, 0 },
10599 { "pipe", TCC_OPTION_pipe
, 0},
10600 { "E", TCC_OPTION_E
, 0},
10604 /* convert 'str' into an array of space separated strings */
10605 static int expand_args(char ***pargv
, const char *str
)
10614 while (is_space(*str
))
10619 while (*str
!= '\0' && !is_space(*str
))
10622 arg
= tcc_malloc(len
+ 1);
10623 memcpy(arg
, s1
, len
);
10625 dynarray_add((void ***)&argv
, &argc
, arg
);
10631 static char **files
;
10632 static int nb_files
, nb_libraries
;
10633 static int multiple_files
;
10634 static int print_search_dirs
;
10635 static int output_type
;
10636 static int reloc_output
;
10637 static const char *outfile
;
10639 int parse_args(TCCState
*s
, int argc
, char **argv
)
10642 const TCCOption
*popt
;
10643 const char *optarg
, *p1
, *r1
;
10648 if (optind
>= argc
) {
10649 if (nb_files
== 0 && !print_search_dirs
)
10654 r
= argv
[optind
++];
10656 /* add a new file */
10657 dynarray_add((void ***)&files
, &nb_files
, r
);
10658 if (!multiple_files
) {
10660 /* argv[0] will be this file */
10664 /* find option in table (match only the first chars */
10665 popt
= tcc_options
;
10669 error("invalid option -- '%s'", r
);
10682 if (popt
->flags
& TCC_OPTION_HAS_ARG
) {
10683 if (*r1
!= '\0' || (popt
->flags
& TCC_OPTION_NOSEP
)) {
10686 if (optind
>= argc
)
10687 error("argument to '%s' is missing", r
);
10688 optarg
= argv
[optind
++];
10696 switch(popt
->index
) {
10697 case TCC_OPTION_HELP
:
10702 if (tcc_add_include_path(s
, optarg
) < 0)
10703 error("too many include paths");
10708 sym
= (char *)optarg
;
10709 value
= strchr(sym
, '=');
10714 tcc_define_symbol(s
, sym
, value
);
10718 tcc_undefine_symbol(s
, optarg
);
10721 tcc_add_library_path(s
, optarg
);
10724 /* set tcc utilities path (mainly for tcc development) */
10725 tcc_lib_path
= optarg
;
10728 dynarray_add((void ***)&files
, &nb_files
, r
);
10731 case TCC_OPTION_bench
:
10734 case TCC_OPTION_bt
:
10735 num_callers
= atoi(optarg
);
10737 #ifdef CONFIG_TCC_BCHECK
10739 do_bounds_check
= 1;
10747 multiple_files
= 1;
10748 output_type
= TCC_OUTPUT_OBJ
;
10750 case TCC_OPTION_static
:
10751 s
->static_link
= 1;
10753 case TCC_OPTION_shared
:
10754 output_type
= TCC_OUTPUT_DLL
;
10757 multiple_files
= 1;
10761 /* generate a .o merging several output files */
10763 output_type
= TCC_OUTPUT_OBJ
;
10765 case TCC_OPTION_nostdinc
:
10768 case TCC_OPTION_nostdlib
:
10771 case TCC_OPTION_print_search_dirs
:
10772 print_search_dirs
= 1;
10774 case TCC_OPTION_run
:
10778 argc1
= expand_args(&argv1
, optarg
);
10780 parse_args(s
, argc1
, argv1
);
10782 multiple_files
= 0;
10783 output_type
= TCC_OUTPUT_MEMORY
;
10787 printf("tcc version %s\n", TCC_VERSION
);
10790 if (tcc_set_flag(s
, optarg
, 1) < 0 && s
->warn_unsupported
)
10791 goto unsupported_option
;
10794 if (tcc_set_warning(s
, optarg
, 1) < 0 &&
10795 s
->warn_unsupported
)
10796 goto unsupported_option
;
10801 case TCC_OPTION_rdynamic
:
10804 case TCC_OPTION_Wl
:
10807 if (strstart(optarg
, "-Ttext,", &p
)) {
10808 s
->text_addr
= strtoul(p
, NULL
, 16);
10809 s
->has_text_addr
= 1;
10810 } else if (strstart(optarg
, "--oformat,", &p
)) {
10811 if (strstart(p
, "elf32-", NULL
)) {
10812 s
->output_format
= TCC_OUTPUT_FORMAT_ELF
;
10813 } else if (!strcmp(p
, "binary")) {
10814 s
->output_format
= TCC_OUTPUT_FORMAT_BINARY
;
10816 #ifdef TCC_TARGET_COFF
10817 if (!strcmp(p
, "coff")) {
10818 s
->output_format
= TCC_OUTPUT_FORMAT_COFF
;
10822 error("target %s not found", p
);
10825 error("unsupported linker option '%s'", optarg
);
10830 output_type
= TCC_OUTPUT_PREPROCESS
;
10833 if (s
->warn_unsupported
) {
10834 unsupported_option
:
10835 warning("unsupported option '%s'", r
);
10844 int main(int argc
, char **argv
)
10848 int nb_objfiles
, ret
, optind
;
10849 char objfilename
[1024];
10850 int64_t start_time
= 0;
10853 tcc_lib_path
= w32_tcc_lib_path();
10857 output_type
= TCC_OUTPUT_EXE
;
10859 multiple_files
= 1;
10864 print_search_dirs
= 0;
10866 optind
= parse_args(s
, argc
- 1, argv
+ 1) + 1;
10868 if (print_search_dirs
) {
10869 /* enough for Linux kernel */
10870 printf("install: %s/\n", tcc_lib_path
);
10874 nb_objfiles
= nb_files
- nb_libraries
;
10876 /* if outfile provided without other options, we output an
10878 if (outfile
&& output_type
== TCC_OUTPUT_MEMORY
)
10879 output_type
= TCC_OUTPUT_EXE
;
10881 /* check -c consistency : only single file handled. XXX: checks file type */
10882 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
10883 /* accepts only a single input file */
10884 if (nb_objfiles
!= 1)
10885 error("cannot specify multiple files with -c");
10886 if (nb_libraries
!= 0)
10887 error("cannot specify libraries with -c");
10891 if (output_type
== TCC_OUTPUT_PREPROCESS
) {
10893 s
->outfile
= stdout
;
10895 s
->outfile
= fopen(outfile
, "wb");
10897 error("could not open '%s", outfile
);
10899 } else if (output_type
!= TCC_OUTPUT_MEMORY
) {
10901 /* compute default outfile name */
10902 pstrcpy(objfilename
, sizeof(objfilename
) - 1,
10904 tcc_basename(files
[0]));
10905 #ifdef TCC_TARGET_PE
10906 pe_guess_outfile(objfilename
, output_type
);
10908 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
10909 char *ext
= strrchr(objfilename
, '.');
10911 goto default_outfile
;
10912 /* add .o extension */
10913 strcpy(ext
+ 1, "o");
10916 pstrcpy(objfilename
, sizeof(objfilename
), "a.out");
10919 outfile
= objfilename
;
10924 start_time
= getclock_us();
10927 tcc_set_output_type(s
, output_type
);
10929 /* compile or add each files or library */
10930 for(i
= 0;i
< nb_files
; i
++) {
10931 const char *filename
;
10933 filename
= files
[i
];
10934 if (output_type
== TCC_OUTPUT_PREPROCESS
) {
10935 tcc_add_file_internal(s
, filename
,
10936 AFF_PRINT_ERROR
| AFF_PREPROCESS
);
10938 if (filename
[0] == '-') {
10939 if (tcc_add_library(s
, filename
+ 2) < 0)
10940 error("cannot find %s", filename
);
10942 if (tcc_add_file(s
, filename
) < 0) {
10950 /* free all files */
10955 total_time
= (double)(getclock_us() - start_time
) / 1000000.0;
10956 if (total_time
< 0.001)
10957 total_time
= 0.001;
10958 if (total_bytes
< 1)
10960 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10961 tok_ident
- TOK_IDENT
, total_lines
, total_bytes
,
10962 total_time
, (int)(total_lines
/ total_time
),
10963 total_bytes
/ total_time
/ 1000000.0);
10966 if (s
->output_type
== TCC_OUTPUT_PREPROCESS
) {
10968 fclose(s
->outfile
);
10970 } else if (s
->output_type
== TCC_OUTPUT_MEMORY
) {
10971 ret
= tcc_run(s
, argc
- optind
, argv
+ optind
);
10973 #ifdef TCC_TARGET_PE
10974 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
10975 ret
= tcc_output_pe(s
, outfile
);
10979 ret
= tcc_output_file(s
, outfile
) ? 1 : 0;
10982 /* XXX: cannot do it with bound checking because of the malloc hooks */
10983 if (!do_bounds_check
)
10988 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size
, mem_max_size
);