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__) || defined(__DragonFly__) \
742 || defined(__OpenBSD__)
743 /* currently incorrect */
744 long double strtold(const char *nptr
, char **endptr
)
746 return (long double)strtod(nptr
, endptr
);
748 float strtof(const char *nptr
, char **endptr
)
750 return (float)strtod(nptr
, endptr
);
753 /* XXX: need to define this to use them in non ISOC99 context */
754 extern float strtof (const char *__nptr
, char **__endptr
);
755 extern long double strtold (const char *__nptr
, char **__endptr
);
758 static char *pstrcpy(char *buf
, int buf_size
, const char *s
);
759 static char *pstrcat(char *buf
, int buf_size
, const char *s
);
760 static char *tcc_basename(const char *name
);
762 static void next(void);
763 static void next_nomacro(void);
764 static void parse_expr_type(CType
*type
);
765 static void expr_type(CType
*type
);
766 static void unary_type(CType
*type
);
767 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
768 int case_reg
, int is_expr
);
769 static int expr_const(void);
770 static void expr_eq(void);
771 static void gexpr(void);
772 static void gen_inline_functions(void);
773 static void decl(int l
);
774 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
775 int first
, int size_only
);
776 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
777 int has_init
, int v
, int scope
);
779 void gv2(int rc1
, int rc2
);
780 void move_reg(int r
, int s
);
781 void save_regs(int n
);
782 void save_reg(int r
);
787 int get_reg_ex(int rc
,int rc2
);
790 struct macro_level
*prev
;
794 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
795 const int *macro_str
, struct macro_level
**can_read_stream
);
797 void force_charshort_cast(int t
);
798 static void gen_cast(CType
*type
);
800 static Sym
*sym_find(int v
);
801 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
);
804 static int type_size(CType
*type
, int *a
);
805 static inline CType
*pointed_type(CType
*type
);
806 static int pointed_size(CType
*type
);
807 static int lvalue_type(int t
);
808 static int parse_btype(CType
*type
, AttributeDef
*ad
);
809 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
);
810 static int compare_types(CType
*type1
, CType
*type2
, int unqualified
);
811 static int is_compatible_types(CType
*type1
, CType
*type2
);
812 static int is_compatible_parameter_types(CType
*type1
, CType
*type2
);
814 int ieee_finite(double d
);
815 void error(const char *fmt
, ...);
819 void lexpand_nr(void);
820 static void vpush_global_sym(CType
*type
, int v
);
821 void vset(CType
*type
, int r
, int v
);
822 void type_to_str(char *buf
, int buf_size
,
823 CType
*type
, const char *varstr
);
824 char *get_tok_str(int v
, CValue
*cv
);
825 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
826 unsigned long offset
, unsigned long size
);
827 static Sym
*external_global_sym(int v
, CType
*type
, int r
);
829 /* section generation */
830 static void section_realloc(Section
*sec
, unsigned long new_size
);
831 static void *section_ptr_add(Section
*sec
, unsigned long size
);
832 static void put_extern_sym(Sym
*sym
, Section
*section
,
833 unsigned long value
, unsigned long size
);
834 static void greloc(Section
*s
, Sym
*sym
, unsigned long addr
, int type
);
835 static int put_elf_str(Section
*s
, const char *sym
);
836 static int put_elf_sym(Section
*s
,
837 unsigned long value
, unsigned long size
,
838 int info
, int other
, int shndx
, const char *name
);
839 static int add_elf_sym(Section
*s
, unsigned long value
, unsigned long size
,
840 int info
, int other
, int sh_num
, const char *name
);
841 static void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
842 int type
, int symbol
);
843 static void put_stabs(const char *str
, int type
, int other
, int desc
,
844 unsigned long value
);
845 static void put_stabs_r(const char *str
, int type
, int other
, int desc
,
846 unsigned long value
, Section
*sec
, int sym_index
);
847 static void put_stabn(int type
, int other
, int desc
, int value
);
848 static void put_stabd(int type
, int other
, int desc
);
849 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
);
851 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
852 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
853 #define AFF_PREPROCESS 0x0004 /* preprocess file */
854 static int tcc_add_file_internal(TCCState
*s
, const char *filename
, int flags
);
857 int tcc_output_coff(TCCState
*s1
, FILE *f
);
860 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
);
861 int pe_load_def_file(struct TCCState
*s1
, FILE *fp
);
862 void pe_setup_paths(struct TCCState
*s1
, int *p_output_type
, const char **p_outfile
, char *first_file
);
863 unsigned long pe_add_runtime(struct TCCState
*s1
);
864 int tcc_output_pe(struct TCCState
*s1
, const char *filename
);
868 #ifdef CONFIG_TCC_ASM
870 typedef struct ExprValue
{
875 #define MAX_ASM_OPERANDS 30
877 typedef struct ASMOperand
{
878 int id
; /* GCC 3 optionnal identifier (0 if number only supported */
880 char asm_str
[16]; /* computed asm string for operand */
881 SValue
*vt
; /* C value of the expression */
882 int ref_index
; /* if >= 0, gives reference to a output constraint */
883 int input_index
; /* if >= 0, gives reference to an input constraint */
884 int priority
; /* priority, used to assign registers */
885 int reg
; /* if >= 0, register number used for this operand */
886 int is_llong
; /* true if double register value */
887 int is_memory
; /* true if memory operand */
888 int is_rw
; /* for '+' modifier */
891 static void asm_expr(TCCState
*s1
, ExprValue
*pe
);
892 static int asm_int_expr(TCCState
*s1
);
893 static int find_constraint(ASMOperand
*operands
, int nb_operands
,
894 const char *name
, const char **pp
);
896 static int tcc_assemble(TCCState
*s1
, int do_preprocess
);
900 static void asm_instr(void);
901 static void asm_global_instr(void);
903 /* true if float/double/long double type */
904 static inline int is_float(int t
)
908 return bt
== VT_LDOUBLE
|| bt
== VT_DOUBLE
|| bt
== VT_FLOAT
;
911 #ifdef TCC_TARGET_I386
912 #include "i386-gen.c"
915 #ifdef TCC_TARGET_ARM
919 #ifdef TCC_TARGET_C67
923 #ifdef CONFIG_TCC_STATIC
925 #define RTLD_LAZY 0x001
926 #define RTLD_NOW 0x002
927 #define RTLD_GLOBAL 0x100
928 #define RTLD_DEFAULT NULL
930 /* dummy function for profiling */
931 void *dlopen(const char *filename
, int flag
)
936 const char *dlerror(void)
941 typedef struct TCCSyms
{
946 #define TCCSYM(a) { #a, &a, },
948 /* add the symbol you want here if no dynamic linking is done */
949 static TCCSyms tcc_syms
[] = {
950 #if !defined(CONFIG_TCCBOOT)
959 void *resolve_sym(TCCState
*s1
, const char *symbol
, int type
)
963 while (p
->str
!= NULL
) {
964 if (!strcmp(p
->str
, symbol
))
971 #elif !defined(_WIN32)
975 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
)
977 return dlsym(RTLD_DEFAULT
, sym
);
982 /********************************************************/
984 /* we use our own 'finite' function to avoid potential problems with
985 non standard math libs */
986 /* XXX: endianness dependent */
987 int ieee_finite(double d
)
990 return ((unsigned)((p
[1] | 0x800fffff) + 1)) >> 31;
993 /* copy a string and truncate it. */
994 static char *pstrcpy(char *buf
, int buf_size
, const char *s
)
1001 q_end
= buf
+ buf_size
- 1;
1013 /* strcat and truncate. */
1014 static char *pstrcat(char *buf
, int buf_size
, const char *s
)
1019 pstrcpy(buf
+ len
, buf_size
- len
, s
);
1023 static int strstart(const char *str
, const char *val
, const char **ptr
)
1028 while (*q
!= '\0') {
1040 char *normalize_slashes(char *path
)
1043 for (p
= path
; *p
; ++p
)
1049 char *w32_tcc_lib_path(void)
1051 /* on win32, we suppose the lib and includes are at the location
1053 char path
[1024], *p
;
1054 GetModuleFileNameA(NULL
, path
, sizeof path
);
1055 p
= tcc_basename(normalize_slashes(strlwr(path
)));
1056 if (p
- 5 > path
&& 0 == strncmp(p
- 5, "/bin/", 5))
1061 return strdup(path
);
1065 void set_pages_executable(void *ptr
, unsigned long length
)
1068 unsigned long old_protect
;
1069 VirtualProtect(ptr
, length
, PAGE_EXECUTE_READWRITE
, &old_protect
);
1071 unsigned long start
, end
;
1072 start
= (unsigned long)ptr
& ~(PAGESIZE
- 1);
1073 end
= (unsigned long)ptr
+ length
;
1074 end
= (end
+ PAGESIZE
- 1) & ~(PAGESIZE
- 1);
1075 mprotect((void *)start
, end
- start
, PROT_READ
| PROT_WRITE
| PROT_EXEC
);
1079 /* memory management */
1085 static inline void tcc_free(void *ptr
)
1088 mem_cur_size
-= malloc_usable_size(ptr
);
1093 static void *tcc_malloc(unsigned long size
)
1098 error("memory full");
1100 mem_cur_size
+= malloc_usable_size(ptr
);
1101 if (mem_cur_size
> mem_max_size
)
1102 mem_max_size
= mem_cur_size
;
1107 static void *tcc_mallocz(unsigned long size
)
1110 ptr
= tcc_malloc(size
);
1111 memset(ptr
, 0, size
);
1115 static inline void *tcc_realloc(void *ptr
, unsigned long size
)
1119 mem_cur_size
-= malloc_usable_size(ptr
);
1121 ptr1
= realloc(ptr
, size
);
1123 /* NOTE: count not correct if alloc error, but not critical */
1124 mem_cur_size
+= malloc_usable_size(ptr1
);
1125 if (mem_cur_size
> mem_max_size
)
1126 mem_max_size
= mem_cur_size
;
1131 static char *tcc_strdup(const char *str
)
1134 ptr
= tcc_malloc(strlen(str
) + 1);
1139 #define free(p) use_tcc_free(p)
1140 #define malloc(s) use_tcc_malloc(s)
1141 #define realloc(p, s) use_tcc_realloc(p, s)
1143 static void dynarray_add(void ***ptab
, int *nb_ptr
, void *data
)
1150 /* every power of two we double array size */
1151 if ((nb
& (nb
- 1)) == 0) {
1156 pp
= tcc_realloc(pp
, nb_alloc
* sizeof(void *));
1158 error("memory full");
1165 /* symbol allocator */
1166 static Sym
*__sym_malloc(void)
1168 Sym
*sym_pool
, *sym
, *last_sym
;
1171 sym_pool
= tcc_malloc(SYM_POOL_NB
* sizeof(Sym
));
1173 last_sym
= sym_free_first
;
1175 for(i
= 0; i
< SYM_POOL_NB
; i
++) {
1176 sym
->next
= last_sym
;
1180 sym_free_first
= last_sym
;
1184 static inline Sym
*sym_malloc(void)
1187 sym
= sym_free_first
;
1189 sym
= __sym_malloc();
1190 sym_free_first
= sym
->next
;
1194 static inline void sym_free(Sym
*sym
)
1196 sym
->next
= sym_free_first
;
1197 sym_free_first
= sym
;
1200 Section
*new_section(TCCState
*s1
, const char *name
, int sh_type
, int sh_flags
)
1204 sec
= tcc_mallocz(sizeof(Section
) + strlen(name
));
1205 strcpy(sec
->name
, name
);
1206 sec
->sh_type
= sh_type
;
1207 sec
->sh_flags
= sh_flags
;
1214 sec
->sh_addralign
= 4;
1217 sec
->sh_addralign
= 1;
1220 sec
->sh_addralign
= 32; /* default conservative alignment */
1224 /* only add section if not private */
1225 if (!(sh_flags
& SHF_PRIVATE
)) {
1226 sec
->sh_num
= s1
->nb_sections
;
1227 dynarray_add((void ***)&s1
->sections
, &s1
->nb_sections
, sec
);
1232 static void free_section(Section
*s
)
1238 /* realloc section and set its content to zero */
1239 static void section_realloc(Section
*sec
, unsigned long new_size
)
1242 unsigned char *data
;
1244 size
= sec
->data_allocated
;
1247 while (size
< new_size
)
1249 data
= tcc_realloc(sec
->data
, size
);
1251 error("memory full");
1252 memset(data
+ sec
->data_allocated
, 0, size
- sec
->data_allocated
);
1254 sec
->data_allocated
= size
;
1257 /* reserve at least 'size' bytes in section 'sec' from
1258 sec->data_offset. */
1259 static void *section_ptr_add(Section
*sec
, unsigned long size
)
1261 unsigned long offset
, offset1
;
1263 offset
= sec
->data_offset
;
1264 offset1
= offset
+ size
;
1265 if (offset1
> sec
->data_allocated
)
1266 section_realloc(sec
, offset1
);
1267 sec
->data_offset
= offset1
;
1268 return sec
->data
+ offset
;
1271 /* return a reference to a section, and create it if it does not
1273 Section
*find_section(TCCState
*s1
, const char *name
)
1277 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1278 sec
= s1
->sections
[i
];
1279 if (!strcmp(name
, sec
->name
))
1282 /* sections are created as PROGBITS */
1283 return new_section(s1
, name
, SHT_PROGBITS
, SHF_ALLOC
);
1286 #define SECTION_ABS ((void *)1)
1288 /* update sym->c so that it points to an external symbol in section
1289 'section' with value 'value' */
1290 static void put_extern_sym2(Sym
*sym
, Section
*section
,
1291 unsigned long value
, unsigned long size
,
1292 int can_add_underscore
)
1294 int sym_type
, sym_bind
, sh_num
, info
;
1299 if (section
== NULL
)
1301 else if (section
== SECTION_ABS
)
1304 sh_num
= section
->sh_num
;
1306 if ((sym
->type
.t
& VT_BTYPE
) == VT_FUNC
)
1307 sym_type
= STT_FUNC
;
1309 sym_type
= STT_OBJECT
;
1310 if (sym
->type
.t
& VT_STATIC
)
1311 sym_bind
= STB_LOCAL
;
1313 sym_bind
= STB_GLOBAL
;
1315 name
= get_tok_str(sym
->v
, NULL
);
1316 #ifdef CONFIG_TCC_BCHECK
1317 if (do_bounds_check
) {
1320 /* XXX: avoid doing that for statics ? */
1321 /* if bound checking is activated, we change some function
1322 names by adding the "__bound" prefix */
1325 /* XXX: we rely only on malloc hooks */
1338 strcpy(buf
, "__bound_");
1345 if (tcc_state
->leading_underscore
&& can_add_underscore
) {
1347 pstrcpy(buf1
+ 1, sizeof(buf1
) - 1, name
);
1350 info
= ELF32_ST_INFO(sym_bind
, sym_type
);
1351 sym
->c
= add_elf_sym(symtab_section
, value
, size
, info
, 0, sh_num
, name
);
1353 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
1354 esym
->st_value
= value
;
1355 esym
->st_size
= size
;
1356 esym
->st_shndx
= sh_num
;
1360 static void put_extern_sym(Sym
*sym
, Section
*section
,
1361 unsigned long value
, unsigned long size
)
1363 put_extern_sym2(sym
, section
, value
, size
, 1);
1366 /* add a new relocation entry to symbol 'sym' in section 's' */
1367 static void greloc(Section
*s
, Sym
*sym
, unsigned long offset
, int type
)
1370 put_extern_sym(sym
, NULL
, 0, 0);
1371 /* now we can add ELF relocation info */
1372 put_elf_reloc(symtab_section
, s
, offset
, type
, sym
->c
);
1375 static inline int isid(int c
)
1377 return (c
>= 'a' && c
<= 'z') ||
1378 (c
>= 'A' && c
<= 'Z') ||
1382 static inline int isnum(int c
)
1384 return c
>= '0' && c
<= '9';
1387 static inline int isoct(int c
)
1389 return c
>= '0' && c
<= '7';
1392 static inline int toup(int c
)
1394 if (c
>= 'a' && c
<= 'z')
1395 return c
- 'a' + 'A';
1400 static void strcat_vprintf(char *buf
, int buf_size
, const char *fmt
, va_list ap
)
1404 vsnprintf(buf
+ len
, buf_size
- len
, fmt
, ap
);
1407 static void strcat_printf(char *buf
, int buf_size
, const char *fmt
, ...)
1411 strcat_vprintf(buf
, buf_size
, fmt
, ap
);
1415 void error1(TCCState
*s1
, int is_warning
, const char *fmt
, va_list ap
)
1422 for(f
= s1
->include_stack
; f
< s1
->include_stack_ptr
; f
++)
1423 strcat_printf(buf
, sizeof(buf
), "In file included from %s:%d:\n",
1424 (*f
)->filename
, (*f
)->line_num
);
1425 if (file
->line_num
> 0) {
1426 strcat_printf(buf
, sizeof(buf
),
1427 "%s:%d: ", file
->filename
, file
->line_num
);
1429 strcat_printf(buf
, sizeof(buf
),
1430 "%s: ", file
->filename
);
1433 strcat_printf(buf
, sizeof(buf
),
1437 strcat_printf(buf
, sizeof(buf
), "warning: ");
1438 strcat_vprintf(buf
, sizeof(buf
), fmt
, ap
);
1440 if (!s1
->error_func
) {
1441 /* default case: stderr */
1442 fprintf(stderr
, "%s\n", buf
);
1444 s1
->error_func(s1
->error_opaque
, buf
);
1446 if (!is_warning
|| s1
->warn_error
)
1451 void tcc_set_error_func(TCCState
*s
, void *error_opaque
,
1452 void (*error_func
)(void *opaque
, const char *msg
))
1454 s
->error_opaque
= error_opaque
;
1455 s
->error_func
= error_func
;
1459 /* error without aborting current compilation */
1460 void error_noabort(const char *fmt
, ...)
1462 TCCState
*s1
= tcc_state
;
1466 error1(s1
, 0, fmt
, ap
);
1470 void error(const char *fmt
, ...)
1472 TCCState
*s1
= tcc_state
;
1476 error1(s1
, 0, fmt
, ap
);
1478 /* better than nothing: in some cases, we accept to handle errors */
1479 if (s1
->error_set_jmp_enabled
) {
1480 longjmp(s1
->error_jmp_buf
, 1);
1482 /* XXX: eliminate this someday */
1487 void expect(const char *msg
)
1489 error("%s expected", msg
);
1492 void warning(const char *fmt
, ...)
1494 TCCState
*s1
= tcc_state
;
1501 error1(s1
, 1, fmt
, ap
);
1508 error("'%c' expected", c
);
1512 static void test_lvalue(void)
1514 if (!(vtop
->r
& VT_LVAL
))
1518 /* allocate a new token */
1519 static TokenSym
*tok_alloc_new(TokenSym
**pts
, const char *str
, int len
)
1521 TokenSym
*ts
, **ptable
;
1524 if (tok_ident
>= SYM_FIRST_ANOM
)
1525 error("memory full");
1527 /* expand token table if needed */
1528 i
= tok_ident
- TOK_IDENT
;
1529 if ((i
% TOK_ALLOC_INCR
) == 0) {
1530 ptable
= tcc_realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
1532 error("memory full");
1533 table_ident
= ptable
;
1536 ts
= tcc_malloc(sizeof(TokenSym
) + len
);
1537 table_ident
[i
] = ts
;
1538 ts
->tok
= tok_ident
++;
1539 ts
->sym_define
= NULL
;
1540 ts
->sym_label
= NULL
;
1541 ts
->sym_struct
= NULL
;
1542 ts
->sym_identifier
= NULL
;
1544 ts
->hash_next
= NULL
;
1545 memcpy(ts
->str
, str
, len
);
1546 ts
->str
[len
] = '\0';
1551 #define TOK_HASH_INIT 1
1552 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1554 /* find a token and add it if not found */
1555 static TokenSym
*tok_alloc(const char *str
, int len
)
1557 TokenSym
*ts
, **pts
;
1563 h
= TOK_HASH_FUNC(h
, ((unsigned char *)str
)[i
]);
1564 h
&= (TOK_HASH_SIZE
- 1);
1566 pts
= &hash_ident
[h
];
1571 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
1573 pts
= &(ts
->hash_next
);
1575 return tok_alloc_new(pts
, str
, len
);
1578 /* CString handling */
1580 static void cstr_realloc(CString
*cstr
, int new_size
)
1585 size
= cstr
->size_allocated
;
1587 size
= 8; /* no need to allocate a too small first string */
1588 while (size
< new_size
)
1590 data
= tcc_realloc(cstr
->data_allocated
, size
);
1592 error("memory full");
1593 cstr
->data_allocated
= data
;
1594 cstr
->size_allocated
= size
;
1599 static inline void cstr_ccat(CString
*cstr
, int ch
)
1602 size
= cstr
->size
+ 1;
1603 if (size
> cstr
->size_allocated
)
1604 cstr_realloc(cstr
, size
);
1605 ((unsigned char *)cstr
->data
)[size
- 1] = ch
;
1609 static void cstr_cat(CString
*cstr
, const char *str
)
1621 /* add a wide char */
1622 static void cstr_wccat(CString
*cstr
, int ch
)
1625 size
= cstr
->size
+ sizeof(nwchar_t
);
1626 if (size
> cstr
->size_allocated
)
1627 cstr_realloc(cstr
, size
);
1628 *(nwchar_t
*)(((unsigned char *)cstr
->data
) + size
- sizeof(nwchar_t
)) = ch
;
1632 static void cstr_new(CString
*cstr
)
1634 memset(cstr
, 0, sizeof(CString
));
1637 /* free string and reset it to NULL */
1638 static void cstr_free(CString
*cstr
)
1640 tcc_free(cstr
->data_allocated
);
1644 #define cstr_reset(cstr) cstr_free(cstr)
1646 /* XXX: unicode ? */
1647 static void add_char(CString
*cstr
, int c
)
1649 if (c
== '\'' || c
== '\"' || c
== '\\') {
1650 /* XXX: could be more precise if char or string */
1651 cstr_ccat(cstr
, '\\');
1653 if (c
>= 32 && c
<= 126) {
1656 cstr_ccat(cstr
, '\\');
1658 cstr_ccat(cstr
, 'n');
1660 cstr_ccat(cstr
, '0' + ((c
>> 6) & 7));
1661 cstr_ccat(cstr
, '0' + ((c
>> 3) & 7));
1662 cstr_ccat(cstr
, '0' + (c
& 7));
1667 /* XXX: buffer overflow */
1668 /* XXX: float tokens */
1669 char *get_tok_str(int v
, CValue
*cv
)
1671 static char buf
[STRING_MAX_SIZE
+ 1];
1672 static CString cstr_buf
;
1678 /* NOTE: to go faster, we give a fixed buffer for small strings */
1679 cstr_reset(&cstr_buf
);
1680 cstr_buf
.data
= buf
;
1681 cstr_buf
.size_allocated
= sizeof(buf
);
1687 /* XXX: not quite exact, but only useful for testing */
1688 sprintf(p
, "%u", cv
->ui
);
1692 /* XXX: not quite exact, but only useful for testing */
1693 sprintf(p
, "%Lu", cv
->ull
);
1697 cstr_ccat(&cstr_buf
, '\'');
1698 add_char(&cstr_buf
, cv
->i
);
1699 cstr_ccat(&cstr_buf
, '\'');
1700 cstr_ccat(&cstr_buf
, '\0');
1704 len
= cstr
->size
- 1;
1706 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1707 cstr_ccat(&cstr_buf
, '\0');
1712 cstr_ccat(&cstr_buf
, '\"');
1714 len
= cstr
->size
- 1;
1716 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1718 len
= (cstr
->size
/ sizeof(nwchar_t
)) - 1;
1720 add_char(&cstr_buf
, ((nwchar_t
*)cstr
->data
)[i
]);
1722 cstr_ccat(&cstr_buf
, '\"');
1723 cstr_ccat(&cstr_buf
, '\0');
1732 return strcpy(p
, "...");
1734 return strcpy(p
, "<<=");
1736 return strcpy(p
, ">>=");
1738 if (v
< TOK_IDENT
) {
1739 /* search in two bytes table */
1753 } else if (v
< tok_ident
) {
1754 return table_ident
[v
- TOK_IDENT
]->str
;
1755 } else if (v
>= SYM_FIRST_ANOM
) {
1756 /* special name for anonymous symbol */
1757 sprintf(p
, "L.%u", v
- SYM_FIRST_ANOM
);
1759 /* should never happen */
1764 return cstr_buf
.data
;
1767 /* push, without hashing */
1768 static Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
1782 /* find a symbol and return its associated structure. 's' is the top
1783 of the symbol stack */
1784 static Sym
*sym_find2(Sym
*s
, int v
)
1794 /* structure lookup */
1795 static inline Sym
*struct_find(int v
)
1798 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1800 return table_ident
[v
]->sym_struct
;
1803 /* find an identifier */
1804 static inline Sym
*sym_find(int v
)
1807 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1809 return table_ident
[v
]->sym_identifier
;
1812 /* push a given symbol on the symbol stack */
1813 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
)
1822 s
= sym_push2(ps
, v
, type
->t
, c
);
1823 s
->type
.ref
= type
->ref
;
1825 /* don't record fields or anonymous symbols */
1827 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1828 /* record symbol in token array */
1829 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1831 ps
= &ts
->sym_struct
;
1833 ps
= &ts
->sym_identifier
;
1840 /* push a global identifier */
1841 static Sym
*global_identifier_push(int v
, int t
, int c
)
1844 s
= sym_push2(&global_stack
, v
, t
, c
);
1845 /* don't record anonymous symbol */
1846 if (v
< SYM_FIRST_ANOM
) {
1847 ps
= &table_ident
[v
- TOK_IDENT
]->sym_identifier
;
1848 /* modify the top most local identifier, so that
1849 sym_identifier will point to 's' when popped */
1851 ps
= &(*ps
)->prev_tok
;
1858 /* pop symbols until top reaches 'b' */
1859 static void sym_pop(Sym
**ptop
, Sym
*b
)
1869 /* remove symbol in token array */
1871 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1872 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1874 ps
= &ts
->sym_struct
;
1876 ps
= &ts
->sym_identifier
;
1887 BufferedFile
*tcc_open(TCCState
*s1
, const char *filename
)
1892 fd
= open(filename
, O_RDONLY
| O_BINARY
);
1895 bf
= tcc_malloc(sizeof(BufferedFile
));
1901 bf
->buf_ptr
= bf
->buffer
;
1902 bf
->buf_end
= bf
->buffer
;
1903 bf
->buffer
[0] = CH_EOB
; /* put eob symbol */
1904 pstrcpy(bf
->filename
, sizeof(bf
->filename
), filename
);
1906 normalize_slashes(bf
->filename
);
1909 bf
->ifndef_macro
= 0;
1910 bf
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
1911 // printf("opening '%s'\n", filename);
1915 void tcc_close(BufferedFile
*bf
)
1917 total_lines
+= bf
->line_num
;
1922 /* fill input buffer and peek next char */
1923 static int tcc_peekc_slow(BufferedFile
*bf
)
1926 /* only tries to read if really end of buffer */
1927 if (bf
->buf_ptr
>= bf
->buf_end
) {
1929 #if defined(PARSE_DEBUG)
1934 len
= read(bf
->fd
, bf
->buffer
, len
);
1941 bf
->buf_ptr
= bf
->buffer
;
1942 bf
->buf_end
= bf
->buffer
+ len
;
1943 *bf
->buf_end
= CH_EOB
;
1945 if (bf
->buf_ptr
< bf
->buf_end
) {
1946 return bf
->buf_ptr
[0];
1948 bf
->buf_ptr
= bf
->buf_end
;
1953 /* return the current character, handling end of block if necessary
1955 static int handle_eob(void)
1957 return tcc_peekc_slow(file
);
1960 /* read next char from current input file and handle end of input buffer */
1961 static inline void inp(void)
1963 ch
= *(++(file
->buf_ptr
));
1964 /* end of buffer/file handling */
1969 /* handle '\[\r]\n' */
1970 static void handle_stray(void)
1972 while (ch
== '\\') {
1977 } else if (ch
== '\r') {
1985 error("stray '\\' in program");
1990 /* skip the stray and handle the \\n case. Output an error if
1991 incorrect char after the stray */
1992 static int handle_stray1(uint8_t *p
)
1996 if (p
>= file
->buf_end
) {
2013 /* handle just the EOB case, but not stray */
2014 #define PEEKC_EOB(c, p)\
2025 /* handle the complicated stray case */
2026 #define PEEKC(c, p)\
2031 c = handle_stray1(p);\
2036 /* input with '\[\r]\n' handling. Note that this function cannot
2037 handle other characters after '\', so you cannot call it inside
2038 strings or comments */
2039 static void minp(void)
2047 /* single line C++ comments */
2048 static uint8_t *parse_line_comment(uint8_t *p
)
2056 if (c
== '\n' || c
== CH_EOF
) {
2058 } else if (c
== '\\') {
2067 } else if (c
== '\r') {
2085 static uint8_t *parse_comment(uint8_t *p
)
2091 /* fast skip loop */
2094 if (c
== '\n' || c
== '*' || c
== '\\')
2098 if (c
== '\n' || c
== '*' || c
== '\\')
2102 /* now we can handle all the cases */
2106 } else if (c
== '*') {
2112 } else if (c
== '/') {
2113 goto end_of_comment
;
2114 } else if (c
== '\\') {
2119 /* skip '\[\r]\n', otherwise just skip the stray */
2125 } else if (c
== '\r') {
2142 /* stray, eob or eof */
2147 error("unexpected end of file in comment");
2148 } else if (c
== '\\') {
2160 /* space exlcuding newline */
2161 static inline int is_space(int ch
)
2163 return ch
== ' ' || ch
== '\t' || ch
== '\v' || ch
== '\f' || ch
== '\r';
2166 static inline void skip_spaces(void)
2168 while (is_space(ch
))
2172 /* parse a string without interpreting escapes */
2173 static uint8_t *parse_pp_string(uint8_t *p
,
2174 int sep
, CString
*str
)
2182 } else if (c
== '\\') {
2187 unterminated_string
:
2188 /* XXX: indicate line number of start of string */
2189 error("missing terminating %c character", sep
);
2190 } else if (c
== '\\') {
2191 /* escape : just skip \[\r]\n */
2196 } else if (c
== '\r') {
2199 expect("'\n' after '\r'");
2202 } else if (c
== CH_EOF
) {
2203 goto unterminated_string
;
2206 cstr_ccat(str
, '\\');
2212 } else if (c
== '\n') {
2215 } else if (c
== '\r') {
2219 cstr_ccat(str
, '\r');
2235 /* skip block of text until #else, #elif or #endif. skip also pairs of
2237 void preprocess_skip(void)
2239 int a
, start_of_line
, c
;
2266 } else if (c
== '\\') {
2267 /* XXX: incorrect: should not give an error */
2268 ch
= file
->buf_ptr
[0];
2276 p
= parse_pp_string(p
, c
, NULL
);
2285 p
= parse_comment(p
);
2286 } else if (ch
== '/') {
2287 p
= parse_line_comment(p
);
2293 if (start_of_line
) {
2298 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
2300 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
2302 else if (tok
== TOK_ENDIF
)
2316 /* ParseState handling */
2318 /* XXX: currently, no include file info is stored. Thus, we cannot display
2319 accurate messages if the function or data definition spans multiple
2322 /* save current parse state in 's' */
2323 void save_parse_state(ParseState
*s
)
2325 s
->line_num
= file
->line_num
;
2326 s
->macro_ptr
= macro_ptr
;
2331 /* restore parse state from 's' */
2332 void restore_parse_state(ParseState
*s
)
2334 file
->line_num
= s
->line_num
;
2335 macro_ptr
= s
->macro_ptr
;
2340 /* return the number of additional 'ints' necessary to store the
2342 static inline int tok_ext_size(int t
)
2356 error("unsupported token");
2363 return LDOUBLE_SIZE
/ 4;
2369 /* token string handling */
2371 static inline void tok_str_new(TokenString
*s
)
2375 s
->allocated_len
= 0;
2376 s
->last_line_num
= -1;
2379 static void tok_str_free(int *str
)
2384 static int *tok_str_realloc(TokenString
*s
)
2388 if (s
->allocated_len
== 0) {
2391 len
= s
->allocated_len
* 2;
2393 str
= tcc_realloc(s
->str
, len
* sizeof(int));
2395 error("memory full");
2396 s
->allocated_len
= len
;
2401 static void tok_str_add(TokenString
*s
, int t
)
2407 if (len
>= s
->allocated_len
)
2408 str
= tok_str_realloc(s
);
2413 static void tok_str_add2(TokenString
*s
, int t
, CValue
*cv
)
2420 /* allocate space for worst case */
2421 if (len
+ TOK_MAX_SIZE
> s
->allocated_len
)
2422 str
= tok_str_realloc(s
);
2431 str
[len
++] = cv
->tab
[0];
2440 nb_words
= (sizeof(CString
) + cv
->cstr
->size
+ 3) >> 2;
2441 while ((len
+ nb_words
) > s
->allocated_len
)
2442 str
= tok_str_realloc(s
);
2443 cstr
= (CString
*)(str
+ len
);
2445 cstr
->size
= cv
->cstr
->size
;
2446 cstr
->data_allocated
= NULL
;
2447 cstr
->size_allocated
= cstr
->size
;
2448 memcpy((char *)cstr
+ sizeof(CString
),
2449 cv
->cstr
->data
, cstr
->size
);
2456 #if LDOUBLE_SIZE == 8
2459 str
[len
++] = cv
->tab
[0];
2460 str
[len
++] = cv
->tab
[1];
2462 #if LDOUBLE_SIZE == 12
2464 str
[len
++] = cv
->tab
[0];
2465 str
[len
++] = cv
->tab
[1];
2466 str
[len
++] = cv
->tab
[2];
2467 #elif LDOUBLE_SIZE != 8
2468 #error add long double size support
2477 /* add the current parse token in token string 's' */
2478 static void tok_str_add_tok(TokenString
*s
)
2482 /* save line number info */
2483 if (file
->line_num
!= s
->last_line_num
) {
2484 s
->last_line_num
= file
->line_num
;
2485 cval
.i
= s
->last_line_num
;
2486 tok_str_add2(s
, TOK_LINENUM
, &cval
);
2488 tok_str_add2(s
, tok
, &tokc
);
2491 #if LDOUBLE_SIZE == 12
2492 #define LDOUBLE_GET(p, cv) \
2496 #elif LDOUBLE_SIZE == 8
2497 #define LDOUBLE_GET(p, cv) \
2501 #error add long double size support
2505 /* get a token from an integer array and increment pointer
2506 accordingly. we code it as a macro to avoid pointer aliasing. */
2507 #define TOK_GET(t, p, cv) \
2522 cv.cstr = (CString *)p; \
2523 cv.cstr->data = (char *)p + sizeof(CString);\
2524 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2533 case TOK_CLDOUBLE: \
2534 LDOUBLE_GET(p, cv); \
2535 p += LDOUBLE_SIZE / 4; \
2542 /* defines handling */
2543 static inline void define_push(int v
, int macro_type
, int *str
, Sym
*first_arg
)
2547 s
= sym_push2(&define_stack
, v
, macro_type
, (int)str
);
2548 s
->next
= first_arg
;
2549 table_ident
[v
- TOK_IDENT
]->sym_define
= s
;
2552 /* undefined a define symbol. Its name is just set to zero */
2553 static void define_undef(Sym
*s
)
2557 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2558 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2562 static inline Sym
*define_find(int v
)
2565 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2567 return table_ident
[v
]->sym_define
;
2570 /* free define stack until top reaches 'b' */
2571 static void free_defines(Sym
*b
)
2579 /* do not free args or predefined defines */
2581 tok_str_free((int *)top
->c
);
2583 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2584 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2592 static Sym
*label_find(int v
)
2595 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2597 return table_ident
[v
]->sym_label
;
2600 static Sym
*label_push(Sym
**ptop
, int v
, int flags
)
2603 s
= sym_push2(ptop
, v
, 0, 0);
2605 ps
= &table_ident
[v
- TOK_IDENT
]->sym_label
;
2606 if (ptop
== &global_label_stack
) {
2607 /* modify the top most local identifier, so that
2608 sym_identifier will point to 's' when popped */
2610 ps
= &(*ps
)->prev_tok
;
2617 /* pop labels until element last is reached. Look if any labels are
2618 undefined. Define symbols if '&&label' was used. */
2619 static void label_pop(Sym
**ptop
, Sym
*slast
)
2622 for(s
= *ptop
; s
!= slast
; s
= s1
) {
2624 if (s
->r
== LABEL_DECLARED
) {
2625 warning("label '%s' declared but not used", get_tok_str(s
->v
, NULL
));
2626 } else if (s
->r
== LABEL_FORWARD
) {
2627 error("label '%s' used but not defined",
2628 get_tok_str(s
->v
, NULL
));
2631 /* define corresponding symbol. A size of
2633 put_extern_sym(s
, cur_text_section
, (long)s
->next
, 1);
2637 table_ident
[s
->v
- TOK_IDENT
]->sym_label
= s
->prev_tok
;
2643 /* eval an expression for #if/#elif */
2644 static int expr_preprocess(void)
2650 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2651 next(); /* do macro subst */
2652 if (tok
== TOK_DEFINED
) {
2657 c
= define_find(tok
) != 0;
2662 } else if (tok
>= TOK_IDENT
) {
2663 /* if undefined macro */
2667 tok_str_add_tok(&str
);
2669 tok_str_add(&str
, -1); /* simulate end of file */
2670 tok_str_add(&str
, 0);
2671 /* now evaluate C constant expression */
2672 macro_ptr
= str
.str
;
2676 tok_str_free(str
.str
);
2680 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2681 static void tok_print(int *str
)
2687 TOK_GET(t
, str
, cval
);
2690 printf(" %s", get_tok_str(t
, &cval
));
2696 /* parse after #define */
2697 static void parse_define(void)
2699 Sym
*s
, *first
, **ps
;
2700 int v
, t
, varg
, is_vaargs
, c
;
2705 error("invalid macro name '%s'", get_tok_str(tok
, &tokc
));
2706 /* XXX: should check if same macro (ANSI) */
2709 /* '(' must be just after macro definition for MACRO_FUNC */
2710 c
= file
->buf_ptr
[0];
2712 c
= handle_stray1(file
->buf_ptr
);
2717 while (tok
!= ')') {
2721 if (varg
== TOK_DOTS
) {
2722 varg
= TOK___VA_ARGS__
;
2724 } else if (tok
== TOK_DOTS
&& gnu_ext
) {
2728 if (varg
< TOK_IDENT
)
2729 error("badly punctuated parameter list");
2730 s
= sym_push2(&define_stack
, varg
| SYM_FIELD
, is_vaargs
, 0);
2741 /* EOF testing necessary for '-D' handling */
2742 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2743 tok_str_add2(&str
, tok
, &tokc
);
2746 tok_str_add(&str
, 0);
2748 printf("define %s %d: ", get_tok_str(v
, NULL
), t
);
2751 define_push(v
, t
, str
.str
, first
);
2754 static inline int hash_cached_include(int type
, const char *filename
)
2756 const unsigned char *s
;
2760 h
= TOK_HASH_FUNC(h
, type
);
2763 h
= TOK_HASH_FUNC(h
, *s
);
2766 h
&= (CACHED_INCLUDES_HASH_SIZE
- 1);
2770 /* XXX: use a token or a hash table to accelerate matching ? */
2771 static CachedInclude
*search_cached_include(TCCState
*s1
,
2772 int type
, const char *filename
)
2776 h
= hash_cached_include(type
, filename
);
2777 i
= s1
->cached_includes_hash
[h
];
2781 e
= s1
->cached_includes
[i
- 1];
2782 if (e
->type
== type
&& !strcmp(e
->filename
, filename
))
2789 static inline void add_cached_include(TCCState
*s1
, int type
,
2790 const char *filename
, int ifndef_macro
)
2795 if (search_cached_include(s1
, type
, filename
))
2798 printf("adding cached '%s' %s\n", filename
, get_tok_str(ifndef_macro
, NULL
));
2800 e
= tcc_malloc(sizeof(CachedInclude
) + strlen(filename
));
2804 strcpy(e
->filename
, filename
);
2805 e
->ifndef_macro
= ifndef_macro
;
2806 dynarray_add((void ***)&s1
->cached_includes
, &s1
->nb_cached_includes
, e
);
2807 /* add in hash table */
2808 h
= hash_cached_include(type
, filename
);
2809 e
->hash_next
= s1
->cached_includes_hash
[h
];
2810 s1
->cached_includes_hash
[h
] = s1
->nb_cached_includes
;
2813 static void pragma_parse(TCCState
*s1
)
2818 if (tok
== TOK_pack
) {
2821 #pragma pack(1) // set
2822 #pragma pack() // reset to default
2823 #pragma pack(push,1) // push & set
2824 #pragma pack(pop) // restore previous
2828 if (tok
== TOK_ASM_pop
) {
2830 if (s1
->pack_stack_ptr
<= s1
->pack_stack
) {
2832 error("out of pack stack");
2834 s1
->pack_stack_ptr
--;
2838 if (tok
== TOK_ASM_push
) {
2840 if (s1
->pack_stack_ptr
>= s1
->pack_stack
+ PACK_STACK_SIZE
- 1)
2842 s1
->pack_stack_ptr
++;
2845 if (tok
!= TOK_CINT
) {
2847 error("invalid pack pragma");
2850 if (val
< 1 || val
> 16 || (val
& (val
- 1)) != 0)
2854 *s1
->pack_stack_ptr
= val
;
2860 /* is_bof is true if first non space token at beginning of file */
2861 static void preprocess(int is_bof
)
2863 TCCState
*s1
= tcc_state
;
2864 int size
, i
, c
, n
, saved_parse_flags
;
2865 char buf
[1024], *q
, *p
;
2871 saved_parse_flags
= parse_flags
;
2872 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
|
2873 PARSE_FLAG_LINEFEED
;
2883 s
= define_find(tok
);
2884 /* undefine symbol by putting an invalid name */
2889 case TOK_INCLUDE_NEXT
:
2890 ch
= file
->buf_ptr
[0];
2891 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2896 } else if (ch
== '\"') {
2899 /* XXX: better stray handling */
2902 while (ch
!= c
&& ch
!= '\n' && ch
!= CH_EOF
) {
2903 if ((q
- buf
) < sizeof(buf
) - 1)
2910 /* eat all spaces and comments after include */
2911 /* XXX: slightly incorrect */
2912 while (ch1
!= '\n' && ch1
!= CH_EOF
)
2916 /* computed #include : either we have only strings or
2917 we have anything enclosed in '<>' */
2920 if (tok
== TOK_STR
) {
2921 while (tok
!= TOK_LINEFEED
) {
2922 if (tok
!= TOK_STR
) {
2924 error("'#include' expects \"FILENAME\" or <FILENAME>");
2926 pstrcat(buf
, sizeof(buf
), (char *)tokc
.cstr
->data
);
2932 while (tok
!= TOK_LINEFEED
) {
2933 pstrcat(buf
, sizeof(buf
), get_tok_str(tok
, &tokc
));
2937 /* check syntax and remove '<>' */
2938 if (len
< 2 || buf
[0] != '<' || buf
[len
- 1] != '>')
2939 goto include_syntax
;
2940 memmove(buf
, buf
+ 1, len
- 2);
2941 buf
[len
- 2] = '\0';
2946 e
= search_cached_include(s1
, c
, buf
);
2947 if (e
&& define_find(e
->ifndef_macro
)) {
2948 /* no need to parse the include because the 'ifndef macro'
2951 printf("%s: skipping %s\n", file
->filename
, buf
);
2955 /* first search in current dir if "header.h" */
2957 p
= strrchr(file
->filename
, '/');
2959 size
= p
+ 1 - file
->filename
;
2960 if (size
> sizeof(buf1
) - 1)
2961 size
= sizeof(buf1
) - 1;
2962 memcpy(buf1
, file
->filename
, size
);
2964 pstrcat(buf1
, sizeof(buf1
), buf
);
2965 f
= tcc_open(s1
, buf1
);
2967 if (tok
== TOK_INCLUDE_NEXT
)
2973 if (s1
->include_stack_ptr
>= s1
->include_stack
+ INCLUDE_STACK_SIZE
)
2974 error("#include recursion too deep");
2975 /* now search in all the include paths */
2976 n
= s1
->nb_include_paths
+ s1
->nb_sysinclude_paths
;
2977 for(i
= 0; i
< n
; i
++) {
2979 if (i
< s1
->nb_include_paths
)
2980 path
= s1
->include_paths
[i
];
2982 path
= s1
->sysinclude_paths
[i
- s1
->nb_include_paths
];
2983 pstrcpy(buf1
, sizeof(buf1
), path
);
2984 pstrcat(buf1
, sizeof(buf1
), "/");
2985 pstrcat(buf1
, sizeof(buf1
), buf
);
2986 f
= tcc_open(s1
, buf1
);
2988 if (tok
== TOK_INCLUDE_NEXT
)
2994 error("include file '%s' not found", buf
);
2998 printf("%s: including %s\n", file
->filename
, buf1
);
3001 pstrcpy(f
->inc_filename
, sizeof(f
->inc_filename
), buf
);
3002 /* push current file in stack */
3003 /* XXX: fix current line init */
3004 *s1
->include_stack_ptr
++ = file
;
3006 /* add include file debug info */
3008 put_stabs(file
->filename
, N_BINCL
, 0, 0, 0);
3010 tok_flags
|= TOK_FLAG_BOF
| TOK_FLAG_BOL
;
3011 ch
= file
->buf_ptr
[0];
3019 c
= expr_preprocess();
3025 if (tok
< TOK_IDENT
)
3026 error("invalid argument for '#if%sdef'", c
? "n" : "");
3030 printf("#ifndef %s\n", get_tok_str(tok
, NULL
));
3032 file
->ifndef_macro
= tok
;
3035 c
= (define_find(tok
) != 0) ^ c
;
3037 if (s1
->ifdef_stack_ptr
>= s1
->ifdef_stack
+ IFDEF_STACK_SIZE
)
3038 error("memory full");
3039 *s1
->ifdef_stack_ptr
++ = c
;
3042 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
3043 error("#else without matching #if");
3044 if (s1
->ifdef_stack_ptr
[-1] & 2)
3045 error("#else after #else");
3046 c
= (s1
->ifdef_stack_ptr
[-1] ^= 3);
3049 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
3050 error("#elif without matching #if");
3051 c
= s1
->ifdef_stack_ptr
[-1];
3053 error("#elif after #else");
3054 /* last #if/#elif expression was true: we skip */
3057 c
= expr_preprocess();
3058 s1
->ifdef_stack_ptr
[-1] = c
;
3068 if (s1
->ifdef_stack_ptr
<= file
->ifdef_stack_ptr
)
3069 error("#endif without matching #if");
3070 s1
->ifdef_stack_ptr
--;
3071 /* '#ifndef macro' was at the start of file. Now we check if
3072 an '#endif' is exactly at the end of file */
3073 if (file
->ifndef_macro
&&
3074 s1
->ifdef_stack_ptr
== file
->ifdef_stack_ptr
) {
3075 file
->ifndef_macro_saved
= file
->ifndef_macro
;
3076 /* need to set to zero to avoid false matches if another
3077 #ifndef at middle of file */
3078 file
->ifndef_macro
= 0;
3079 while (tok
!= TOK_LINEFEED
)
3081 tok_flags
|= TOK_FLAG_ENDIF
;
3087 if (tok
!= TOK_CINT
)
3089 file
->line_num
= tokc
.i
- 1; /* the line number will be incremented after */
3091 if (tok
!= TOK_LINEFEED
) {
3094 pstrcpy(file
->filename
, sizeof(file
->filename
),
3095 (char *)tokc
.cstr
->data
);
3101 ch
= file
->buf_ptr
[0];
3104 while (ch
!= '\n' && ch
!= CH_EOF
) {
3105 if ((q
- buf
) < sizeof(buf
) - 1)
3111 error("#error %s", buf
);
3113 warning("#warning %s", buf
);
3119 if (tok
== TOK_LINEFEED
|| tok
== '!' || tok
== TOK_CINT
) {
3120 /* '!' is ignored to allow C scripts. numbers are ignored
3121 to emulate cpp behaviour */
3123 if (!(saved_parse_flags
& PARSE_FLAG_ASM_COMMENTS
))
3124 error("invalid preprocessing directive #%s", get_tok_str(tok
, &tokc
));
3128 /* ignore other preprocess commands or #! for C scripts */
3129 while (tok
!= TOK_LINEFEED
)
3132 parse_flags
= saved_parse_flags
;
3135 /* evaluate escape codes in a string. */
3136 static void parse_escape_string(CString
*outstr
, const uint8_t *buf
, int is_long
)
3151 case '0': case '1': case '2': case '3':
3152 case '4': case '5': case '6': case '7':
3153 /* at most three octal digits */
3158 n
= n
* 8 + c
- '0';
3162 n
= n
* 8 + c
- '0';
3167 goto add_char_nonext
;
3175 if (c
>= 'a' && c
<= 'f')
3177 else if (c
>= 'A' && c
<= 'F')
3187 goto add_char_nonext
;
3211 goto invalid_escape
;
3221 if (c
>= '!' && c
<= '~')
3222 warning("unknown escape sequence: \'\\%c\'", c
);
3224 warning("unknown escape sequence: \'\\x%x\'", c
);
3231 cstr_ccat(outstr
, c
);
3233 cstr_wccat(outstr
, c
);
3235 /* add a trailing '\0' */
3237 cstr_ccat(outstr
, '\0');
3239 cstr_wccat(outstr
, '\0');
3242 /* we use 64 bit numbers */
3245 /* bn = (bn << shift) | or_val */
3246 void bn_lshift(unsigned int *bn
, int shift
, int or_val
)
3250 for(i
=0;i
<BN_SIZE
;i
++) {
3252 bn
[i
] = (v
<< shift
) | or_val
;
3253 or_val
= v
>> (32 - shift
);
3257 void bn_zero(unsigned int *bn
)
3260 for(i
=0;i
<BN_SIZE
;i
++) {
3265 /* parse number in null terminated string 'p' and return it in the
3267 void parse_number(const char *p
)
3269 int b
, t
, shift
, frac_bits
, s
, exp_val
, ch
;
3271 unsigned int bn
[BN_SIZE
];
3282 goto float_frac_parse
;
3283 } else if (t
== '0') {
3284 if (ch
== 'x' || ch
== 'X') {
3288 } else if (tcc_ext
&& (ch
== 'b' || ch
== 'B')) {
3294 /* parse all digits. cannot check octal numbers at this stage
3295 because of floating point constants */
3297 if (ch
>= 'a' && ch
<= 'f')
3299 else if (ch
>= 'A' && ch
<= 'F')
3307 if (q
>= token_buf
+ STRING_MAX_SIZE
) {
3309 error("number too long");
3315 ((ch
== 'e' || ch
== 'E') && b
== 10) ||
3316 ((ch
== 'p' || ch
== 'P') && (b
== 16 || b
== 2))) {
3318 /* NOTE: strtox should support that for hexa numbers, but
3319 non ISOC99 libcs do not support it, so we prefer to do
3321 /* hexadecimal or binary floats */
3322 /* XXX: handle overflows */
3334 } else if (t
>= 'a') {
3336 } else if (t
>= 'A') {
3341 bn_lshift(bn
, shift
, t
);
3348 if (t
>= 'a' && t
<= 'f') {
3350 } else if (t
>= 'A' && t
<= 'F') {
3352 } else if (t
>= '0' && t
<= '9') {
3358 error("invalid digit");
3359 bn_lshift(bn
, shift
, t
);
3364 if (ch
!= 'p' && ch
!= 'P')
3371 } else if (ch
== '-') {
3375 if (ch
< '0' || ch
> '9')
3376 expect("exponent digits");
3377 while (ch
>= '0' && ch
<= '9') {
3378 exp_val
= exp_val
* 10 + ch
- '0';
3381 exp_val
= exp_val
* s
;
3383 /* now we can generate the number */
3384 /* XXX: should patch directly float number */
3385 d
= (double)bn
[1] * 4294967296.0 + (double)bn
[0];
3386 d
= ldexp(d
, exp_val
- frac_bits
);
3391 /* float : should handle overflow */
3393 } else if (t
== 'L') {
3396 /* XXX: not large enough */
3397 tokc
.ld
= (long double)d
;
3403 /* decimal floats */
3405 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3410 while (ch
>= '0' && ch
<= '9') {
3411 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3417 if (ch
== 'e' || ch
== 'E') {
3418 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3422 if (ch
== '-' || ch
== '+') {
3423 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3428 if (ch
< '0' || ch
> '9')
3429 expect("exponent digits");
3430 while (ch
>= '0' && ch
<= '9') {
3431 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3443 tokc
.f
= strtof(token_buf
, NULL
);
3444 } else if (t
== 'L') {
3447 tokc
.ld
= strtold(token_buf
, NULL
);
3450 tokc
.d
= strtod(token_buf
, NULL
);
3454 unsigned long long n
, n1
;
3457 /* integer number */
3460 if (b
== 10 && *q
== '0') {
3467 /* no need for checks except for base 10 / 8 errors */
3470 } else if (t
>= 'a') {
3472 } else if (t
>= 'A') {
3477 error("invalid digit");
3481 /* detect overflow */
3482 /* XXX: this test is not reliable */
3484 error("integer constant overflow");
3487 /* XXX: not exactly ANSI compliant */
3488 if ((n
& 0xffffffff00000000LL
) != 0) {
3493 } else if (n
> 0x7fffffff) {
3504 error("three 'l's in integer constant");
3507 if (tok
== TOK_CINT
)
3509 else if (tok
== TOK_CUINT
)
3513 } else if (t
== 'U') {
3515 error("two 'u's in integer constant");
3517 if (tok
== TOK_CINT
)
3519 else if (tok
== TOK_CLLONG
)
3526 if (tok
== TOK_CINT
|| tok
== TOK_CUINT
)
3534 #define PARSE2(c1, tok1, c2, tok2) \
3545 /* return next token without macro substitution */
3546 static inline void next_nomacro1(void)
3566 /* first look if it is in fact an end of buffer */
3567 if (p
>= file
->buf_end
) {
3571 if (p
>= file
->buf_end
)
3584 TCCState
*s1
= tcc_state
;
3585 if ((parse_flags
& PARSE_FLAG_LINEFEED
)
3586 && !(tok_flags
& TOK_FLAG_EOF
)) {
3587 tok_flags
|= TOK_FLAG_EOF
;
3589 goto keep_tok_flags
;
3590 } else if (s1
->include_stack_ptr
== s1
->include_stack
||
3591 !(parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3592 /* no include left : end of file. */
3595 tok_flags
&= ~TOK_FLAG_EOF
;
3596 /* pop include file */
3598 /* test if previous '#endif' was after a #ifdef at
3600 if (tok_flags
& TOK_FLAG_ENDIF
) {
3602 printf("#endif %s\n", get_tok_str(file
->ifndef_macro_saved
, NULL
));
3604 add_cached_include(s1
, file
->inc_type
, file
->inc_filename
,
3605 file
->ifndef_macro_saved
);
3608 /* add end of include file debug info */
3610 put_stabd(N_EINCL
, 0, 0);
3612 /* pop include stack */
3614 s1
->include_stack_ptr
--;
3615 file
= *s1
->include_stack_ptr
;
3624 tok_flags
|= TOK_FLAG_BOL
;
3626 if (0 == (parse_flags
& PARSE_FLAG_LINEFEED
))
3629 goto keep_tok_flags
;
3634 if ((tok_flags
& TOK_FLAG_BOL
) &&
3635 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3637 preprocess(tok_flags
& TOK_FLAG_BOF
);
3643 tok
= TOK_TWOSHARPS
;
3645 if (parse_flags
& PARSE_FLAG_ASM_COMMENTS
) {
3646 p
= parse_line_comment(p
- 1);
3655 case 'a': case 'b': case 'c': case 'd':
3656 case 'e': case 'f': case 'g': case 'h':
3657 case 'i': case 'j': case 'k': case 'l':
3658 case 'm': case 'n': case 'o': case 'p':
3659 case 'q': case 'r': case 's': case 't':
3660 case 'u': case 'v': case 'w': case 'x':
3662 case 'A': case 'B': case 'C': case 'D':
3663 case 'E': case 'F': case 'G': case 'H':
3664 case 'I': case 'J': case 'K':
3665 case 'M': case 'N': case 'O': case 'P':
3666 case 'Q': case 'R': case 'S': case 'T':
3667 case 'U': case 'V': case 'W': case 'X':
3673 h
= TOK_HASH_FUNC(h
, c
);
3677 if (!isidnum_table
[c
])
3679 h
= TOK_HASH_FUNC(h
, c
);
3686 /* fast case : no stray found, so we have the full token
3687 and we have already hashed it */
3689 h
&= (TOK_HASH_SIZE
- 1);
3690 pts
= &hash_ident
[h
];
3695 if (ts
->len
== len
&& !memcmp(ts
->str
, p1
, len
))
3697 pts
= &(ts
->hash_next
);
3699 ts
= tok_alloc_new(pts
, p1
, len
);
3703 cstr_reset(&tokcstr
);
3706 cstr_ccat(&tokcstr
, *p1
);
3712 while (isidnum_table
[c
]) {
3713 cstr_ccat(&tokcstr
, c
);
3716 ts
= tok_alloc(tokcstr
.data
, tokcstr
.size
);
3722 if (t
!= '\\' && t
!= '\'' && t
!= '\"') {
3724 goto parse_ident_fast
;
3727 if (c
== '\'' || c
== '\"') {
3731 cstr_reset(&tokcstr
);
3732 cstr_ccat(&tokcstr
, 'L');
3733 goto parse_ident_slow
;
3737 case '0': case '1': case '2': case '3':
3738 case '4': case '5': case '6': case '7':
3741 cstr_reset(&tokcstr
);
3742 /* after the first digit, accept digits, alpha, '.' or sign if
3743 prefixed by 'eEpP' */
3747 cstr_ccat(&tokcstr
, c
);
3749 if (!(isnum(c
) || isid(c
) || c
== '.' ||
3750 ((c
== '+' || c
== '-') &&
3751 (t
== 'e' || t
== 'E' || t
== 'p' || t
== 'P'))))
3754 /* We add a trailing '\0' to ease parsing */
3755 cstr_ccat(&tokcstr
, '\0');
3756 tokc
.cstr
= &tokcstr
;
3760 /* special dot handling because it can also start a number */
3763 cstr_reset(&tokcstr
);
3764 cstr_ccat(&tokcstr
, '.');
3766 } else if (c
== '.') {
3786 /* parse the string */
3788 p
= parse_pp_string(p
, sep
, &str
);
3789 cstr_ccat(&str
, '\0');
3791 /* eval the escape (should be done as TOK_PPNUM) */
3792 cstr_reset(&tokcstr
);
3793 parse_escape_string(&tokcstr
, str
.data
, is_long
);
3798 /* XXX: make it portable */
3802 char_size
= sizeof(nwchar_t
);
3803 if (tokcstr
.size
<= char_size
)
3804 error("empty character constant");
3805 if (tokcstr
.size
> 2 * char_size
)
3806 warning("multi-character character constant");
3808 tokc
.i
= *(int8_t *)tokcstr
.data
;
3811 tokc
.i
= *(nwchar_t
*)tokcstr
.data
;
3815 tokc
.cstr
= &tokcstr
;
3829 } else if (c
== '<') {
3847 } else if (c
== '>') {
3865 } else if (c
== '=') {
3878 } else if (c
== '=') {
3891 } else if (c
== '=') {
3904 } else if (c
== '=') {
3907 } else if (c
== '>') {
3915 PARSE2('!', '!', '=', TOK_NE
)
3916 PARSE2('=', '=', '=', TOK_EQ
)
3917 PARSE2('*', '*', '=', TOK_A_MUL
)
3918 PARSE2('%', '%', '=', TOK_A_MOD
)
3919 PARSE2('^', '^', '=', TOK_A_XOR
)
3921 /* comments or operator */
3925 p
= parse_comment(p
);
3927 } else if (c
== '/') {
3928 p
= parse_line_comment(p
);
3930 } else if (c
== '=') {
3950 case '$': /* only used in assembler */
3951 case '@': /* dito */
3956 error("unrecognized character \\x%02x", c
);
3962 #if defined(PARSE_DEBUG)
3963 printf("token = %s\n", get_tok_str(tok
, &tokc
));
3967 /* return next token without macro substitution. Can read input from
3969 static void next_nomacro(void)
3975 TOK_GET(tok
, macro_ptr
, tokc
);
3976 if (tok
== TOK_LINENUM
) {
3977 file
->line_num
= tokc
.i
;
3986 /* substitute args in macro_str and return allocated string */
3987 static int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
3989 int *st
, last_tok
, t
, notfirst
;
3998 TOK_GET(t
, macro_str
, cval
);
4003 TOK_GET(t
, macro_str
, cval
);
4006 s
= sym_find2(args
, t
);
4013 cstr_ccat(&cstr
, ' ');
4014 TOK_GET(t
, st
, cval
);
4015 cstr_cat(&cstr
, get_tok_str(t
, &cval
));
4018 cstr_ccat(&cstr
, '\0');
4020 printf("stringize: %s\n", (char *)cstr
.data
);
4024 tok_str_add2(&str
, TOK_STR
, &cval
);
4027 tok_str_add2(&str
, t
, &cval
);
4029 } else if (t
>= TOK_IDENT
) {
4030 s
= sym_find2(args
, t
);
4033 /* if '##' is present before or after, no arg substitution */
4034 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
4035 /* special case for var arg macros : ## eats the
4036 ',' if empty VA_ARGS variable. */
4037 /* XXX: test of the ',' is not 100%
4038 reliable. should fix it to avoid security
4040 if (gnu_ext
&& s
->type
.t
&&
4041 last_tok
== TOK_TWOSHARPS
&&
4042 str
.len
>= 2 && str
.str
[str
.len
- 2] == ',') {
4044 /* suppress ',' '##' */
4047 /* suppress '##' and add variable */
4055 TOK_GET(t1
, st
, cval
);
4058 tok_str_add2(&str
, t1
, &cval
);
4062 /* NOTE: the stream cannot be read when macro
4063 substituing an argument */
4064 macro_subst(&str
, nested_list
, st
, NULL
);
4067 tok_str_add(&str
, t
);
4070 tok_str_add2(&str
, t
, &cval
);
4074 tok_str_add(&str
, 0);
4078 static char const ab_month_name
[12][4] =
4080 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4081 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4084 /* do macro substitution of current token with macro 's' and add
4085 result to (tok_str,tok_len). 'nested_list' is the list of all
4086 macros we got inside to avoid recursing. Return non zero if no
4087 substitution needs to be done */
4088 static int macro_subst_tok(TokenString
*tok_str
,
4089 Sym
**nested_list
, Sym
*s
, struct macro_level
**can_read_stream
)
4091 Sym
*args
, *sa
, *sa1
;
4092 int mstr_allocated
, parlevel
, *mstr
, t
, t1
;
4099 /* if symbol is a macro, prepare substitution */
4100 /* special macros */
4101 if (tok
== TOK___LINE__
) {
4102 snprintf(buf
, sizeof(buf
), "%d", file
->line_num
);
4106 } else if (tok
== TOK___FILE__
) {
4107 cstrval
= file
->filename
;
4109 } else if (tok
== TOK___DATE__
|| tok
== TOK___TIME__
) {
4114 tm
= localtime(&ti
);
4115 if (tok
== TOK___DATE__
) {
4116 snprintf(buf
, sizeof(buf
), "%s %2d %d",
4117 ab_month_name
[tm
->tm_mon
], tm
->tm_mday
, tm
->tm_year
+ 1900);
4119 snprintf(buf
, sizeof(buf
), "%02d:%02d:%02d",
4120 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
);
4127 cstr_cat(&cstr
, cstrval
);
4128 cstr_ccat(&cstr
, '\0');
4130 tok_str_add2(tok_str
, t1
, &cval
);
4135 if (s
->type
.t
== MACRO_FUNC
) {
4136 /* NOTE: we do not use next_nomacro to avoid eating the
4137 next token. XXX: find better solution */
4141 if (t
== 0 && can_read_stream
) {
4142 /* end of macro stream: we must look at the token
4143 after in the file */
4144 struct macro_level
*ml
= *can_read_stream
;
4150 *can_read_stream
= ml
-> prev
;
4155 /* XXX: incorrect with comments */
4156 ch
= file
->buf_ptr
[0];
4157 while (is_space(ch
) || ch
== '\n')
4161 if (t
!= '(') /* no macro subst */
4164 /* argument macro */
4169 /* NOTE: empty args are allowed, except if no args */
4171 /* handle '()' case */
4172 if (!args
&& !sa
&& tok
== ')')
4175 error("macro '%s' used with too many args",
4176 get_tok_str(s
->v
, 0));
4179 /* NOTE: non zero sa->t indicates VA_ARGS */
4180 while ((parlevel
> 0 ||
4182 (tok
!= ',' || sa
->type
.t
))) &&
4186 else if (tok
== ')')
4188 if (tok
!= TOK_LINEFEED
)
4189 tok_str_add2(&str
, tok
, &tokc
);
4192 tok_str_add(&str
, 0);
4193 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, sa
->type
.t
, (int)str
.str
);
4196 /* special case for gcc var args: add an empty
4197 var arg argument if it is omitted */
4198 if (sa
&& sa
->type
.t
&& gnu_ext
)
4208 error("macro '%s' used with too few args",
4209 get_tok_str(s
->v
, 0));
4212 /* now subst each arg */
4213 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
4218 tok_str_free((int *)sa
->c
);
4224 sym_push2(nested_list
, s
->v
, 0, 0);
4225 macro_subst(tok_str
, nested_list
, mstr
, can_read_stream
);
4226 /* pop nested defined symbol */
4228 *nested_list
= sa1
->prev
;
4236 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4237 return the resulting string (which must be freed). */
4238 static inline int *macro_twosharps(const int *macro_str
)
4241 const int *macro_ptr1
, *start_macro_ptr
, *ptr
, *saved_macro_ptr
;
4243 const char *p1
, *p2
;
4245 TokenString macro_str1
;
4248 start_macro_ptr
= macro_str
;
4249 /* we search the first '##' */
4251 macro_ptr1
= macro_str
;
4252 TOK_GET(t
, macro_str
, cval
);
4253 /* nothing more to do if end of string */
4256 if (*macro_str
== TOK_TWOSHARPS
)
4260 /* we saw '##', so we need more processing to handle it */
4262 tok_str_new(¯o_str1
);
4266 /* add all tokens seen so far */
4267 for(ptr
= start_macro_ptr
; ptr
< macro_ptr1
;) {
4268 TOK_GET(t
, ptr
, cval
);
4269 tok_str_add2(¯o_str1
, t
, &cval
);
4271 saved_macro_ptr
= macro_ptr
;
4272 /* XXX: get rid of the use of macro_ptr here */
4273 macro_ptr
= (int *)macro_str
;
4275 while (*macro_ptr
== TOK_TWOSHARPS
) {
4277 macro_ptr1
= macro_ptr
;
4280 TOK_GET(t
, macro_ptr
, cval
);
4281 /* We concatenate the two tokens if we have an
4282 identifier or a preprocessing number */
4284 p1
= get_tok_str(tok
, &tokc
);
4285 cstr_cat(&cstr
, p1
);
4286 p2
= get_tok_str(t
, &cval
);
4287 cstr_cat(&cstr
, p2
);
4288 cstr_ccat(&cstr
, '\0');
4290 if ((tok
>= TOK_IDENT
|| tok
== TOK_PPNUM
) &&
4291 (t
>= TOK_IDENT
|| t
== TOK_PPNUM
)) {
4292 if (tok
== TOK_PPNUM
) {
4293 /* if number, then create a number token */
4294 /* NOTE: no need to allocate because
4295 tok_str_add2() does it */
4296 cstr_reset(&tokcstr
);
4299 tokc
.cstr
= &tokcstr
;
4301 /* if identifier, we must do a test to
4302 validate we have a correct identifier */
4303 if (t
== TOK_PPNUM
) {
4313 if (!isnum(c
) && !isid(c
))
4317 ts
= tok_alloc(cstr
.data
, strlen(cstr
.data
));
4318 tok
= ts
->tok
; /* modify current token */
4321 const char *str
= cstr
.data
;
4322 const unsigned char *q
;
4324 /* we look for a valid token */
4325 /* XXX: do more extensive checks */
4326 if (!strcmp(str
, ">>=")) {
4328 } else if (!strcmp(str
, "<<=")) {
4330 } else if (strlen(str
) == 2) {
4331 /* search in two bytes table */
4336 if (q
[0] == str
[0] && q
[1] == str
[1])
4343 /* NOTE: because get_tok_str use a static buffer,
4346 p1
= get_tok_str(tok
, &tokc
);
4347 cstr_cat(&cstr
, p1
);
4348 cstr_ccat(&cstr
, '\0');
4349 p2
= get_tok_str(t
, &cval
);
4350 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr
.data
, p2
);
4351 /* cannot merge tokens: just add them separately */
4352 tok_str_add2(¯o_str1
, tok
, &tokc
);
4353 /* XXX: free associated memory ? */
4360 tok_str_add2(¯o_str1
, tok
, &tokc
);
4365 macro_ptr
= (int *)saved_macro_ptr
;
4367 tok_str_add(¯o_str1
, 0);
4368 return macro_str1
.str
;
4372 /* do macro substitution of macro_str and add result to
4373 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4374 inside to avoid recursing. */
4375 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
4376 const int *macro_str
, struct macro_level
** can_read_stream
)
4383 struct macro_level ml
;
4385 /* first scan for '##' operator handling */
4387 macro_str1
= macro_twosharps(ptr
);
4391 /* NOTE: ptr == NULL can only happen if tokens are read from
4392 file stream due to a macro function call */
4395 TOK_GET(t
, ptr
, cval
);
4400 /* if nested substitution, do nothing */
4401 if (sym_find2(*nested_list
, t
))
4404 if (can_read_stream
)
4405 ml
.prev
= *can_read_stream
, *can_read_stream
= &ml
;
4406 macro_ptr
= (int *)ptr
;
4408 ret
= macro_subst_tok(tok_str
, nested_list
, s
, can_read_stream
);
4409 ptr
= (int *)macro_ptr
;
4411 if (can_read_stream
&& *can_read_stream
== &ml
)
4412 *can_read_stream
= ml
.prev
;
4417 tok_str_add2(tok_str
, t
, &cval
);
4421 tok_str_free(macro_str1
);
4424 /* return next token with macro substitution */
4425 static void next(void)
4427 Sym
*nested_list
, *s
;
4429 struct macro_level
*ml
;
4434 /* if not reading from macro substituted string, then try
4435 to substitute macros */
4436 if (tok
>= TOK_IDENT
&&
4437 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
4438 s
= define_find(tok
);
4440 /* we have a macro: we try to substitute */
4444 if (macro_subst_tok(&str
, &nested_list
, s
, &ml
) == 0) {
4445 /* substitution done, NOTE: maybe empty */
4446 tok_str_add(&str
, 0);
4447 macro_ptr
= str
.str
;
4448 macro_ptr_allocated
= str
.str
;
4455 /* end of macro or end of unget buffer */
4456 if (unget_buffer_enabled
) {
4457 macro_ptr
= unget_saved_macro_ptr
;
4458 unget_buffer_enabled
= 0;
4460 /* end of macro string: free it */
4461 tok_str_free(macro_ptr_allocated
);
4468 /* convert preprocessor tokens into C tokens */
4469 if (tok
== TOK_PPNUM
&&
4470 (parse_flags
& PARSE_FLAG_TOK_NUM
)) {
4471 parse_number((char *)tokc
.cstr
->data
);
4475 /* push back current token and set current token to 'last_tok'. Only
4476 identifier case handled for labels. */
4477 static inline void unget_tok(int last_tok
)
4481 unget_saved_macro_ptr
= macro_ptr
;
4482 unget_buffer_enabled
= 1;
4483 q
= unget_saved_buffer
;
4486 n
= tok_ext_size(tok
) - 1;
4489 *q
= 0; /* end of token string */
4494 void swap(int *p
, int *q
)
4502 void vsetc(CType
*type
, int r
, CValue
*vc
)
4506 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4507 error("memory full");
4508 /* cannot let cpu flags if other instruction are generated. Also
4509 avoid leaving VT_JMP anywhere except on the top of the stack
4510 because it would complicate the code generator. */
4511 if (vtop
>= vstack
) {
4512 v
= vtop
->r
& VT_VALMASK
;
4513 if (v
== VT_CMP
|| (v
& ~1) == VT_JMP
)
4519 vtop
->r2
= VT_CONST
;
4523 /* push integer constant */
4528 vsetc(&int_type
, VT_CONST
, &cval
);
4531 /* Return a static symbol pointing to a section */
4532 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
4533 unsigned long offset
, unsigned long size
)
4539 sym
= global_identifier_push(v
, type
->t
| VT_STATIC
, 0);
4540 sym
->type
.ref
= type
->ref
;
4541 sym
->r
= VT_CONST
| VT_SYM
;
4542 put_extern_sym(sym
, sec
, offset
, size
);
4546 /* push a reference to a section offset by adding a dummy symbol */
4547 static void vpush_ref(CType
*type
, Section
*sec
, unsigned long offset
, unsigned long size
)
4552 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4553 vtop
->sym
= get_sym_ref(type
, sec
, offset
, size
);
4556 /* define a new external reference to a symbol 'v' of type 'u' */
4557 static Sym
*external_global_sym(int v
, CType
*type
, int r
)
4563 /* push forward reference */
4564 s
= global_identifier_push(v
, type
->t
| VT_EXTERN
, 0);
4565 s
->type
.ref
= type
->ref
;
4566 s
->r
= r
| VT_CONST
| VT_SYM
;
4571 /* define a new external reference to a symbol 'v' of type 'u' */
4572 static Sym
*external_sym(int v
, CType
*type
, int r
)
4578 /* push forward reference */
4579 s
= sym_push(v
, type
, r
| VT_CONST
| VT_SYM
, 0);
4580 s
->type
.t
|= VT_EXTERN
;
4582 if (!is_compatible_types(&s
->type
, type
))
4583 error("incompatible types for redefinition of '%s'",
4584 get_tok_str(v
, NULL
));
4589 /* push a reference to global symbol v */
4590 static void vpush_global_sym(CType
*type
, int v
)
4595 sym
= external_global_sym(v
, type
, 0);
4597 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4601 void vset(CType
*type
, int r
, int v
)
4606 vsetc(type
, r
, &cval
);
4609 void vseti(int r
, int v
)
4625 void vpushv(SValue
*v
)
4627 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4628 error("memory full");
4638 /* save r to the memory stack, and mark it as being free */
4639 void save_reg(int r
)
4641 int l
, saved
, size
, align
;
4645 /* modify all stack values */
4648 for(p
=vstack
;p
<=vtop
;p
++) {
4649 if ((p
->r
& VT_VALMASK
) == r
||
4650 ((p
->type
.t
& VT_BTYPE
) == VT_LLONG
&& (p
->r2
& VT_VALMASK
) == r
)) {
4651 /* must save value on stack if not already done */
4653 /* NOTE: must reload 'r' because r might be equal to r2 */
4654 r
= p
->r
& VT_VALMASK
;
4655 /* store register in the stack */
4657 if ((p
->r
& VT_LVAL
) ||
4658 (!is_float(type
->t
) && (type
->t
& VT_BTYPE
) != VT_LLONG
))
4660 size
= type_size(type
, &align
);
4661 loc
= (loc
- size
) & -align
;
4662 sv
.type
.t
= type
->t
;
4663 sv
.r
= VT_LOCAL
| VT_LVAL
;
4666 #ifdef TCC_TARGET_I386
4667 /* x86 specific: need to pop fp register ST0 if saved */
4668 if (r
== TREG_ST0
) {
4669 o(0xd9dd); /* fstp %st(1) */
4672 /* special long long case */
4673 if ((type
->t
& VT_BTYPE
) == VT_LLONG
) {
4680 /* mark that stack entry as being saved on the stack */
4681 if (p
->r
& VT_LVAL
) {
4682 /* also clear the bounded flag because the
4683 relocation address of the function was stored in
4685 p
->r
= (p
->r
& ~(VT_VALMASK
| VT_BOUNDED
)) | VT_LLOCAL
;
4687 p
->r
= lvalue_type(p
->type
.t
) | VT_LOCAL
;
4695 /* find a register of class 'rc2' with at most one reference on stack.
4696 * If none, call get_reg(rc) */
4697 int get_reg_ex(int rc
, int rc2
)
4702 for(r
=0;r
<NB_REGS
;r
++) {
4703 if (reg_classes
[r
] & rc2
) {
4706 for(p
= vstack
; p
<= vtop
; p
++) {
4707 if ((p
->r
& VT_VALMASK
) == r
||
4708 (p
->r2
& VT_VALMASK
) == r
)
4718 /* find a free register of class 'rc'. If none, save one register */
4724 /* find a free register */
4725 for(r
=0;r
<NB_REGS
;r
++) {
4726 if (reg_classes
[r
] & rc
) {
4727 for(p
=vstack
;p
<=vtop
;p
++) {
4728 if ((p
->r
& VT_VALMASK
) == r
||
4729 (p
->r2
& VT_VALMASK
) == r
)
4737 /* no register left : free the first one on the stack (VERY
4738 IMPORTANT to start from the bottom to ensure that we don't
4739 spill registers used in gen_opi()) */
4740 for(p
=vstack
;p
<=vtop
;p
++) {
4741 r
= p
->r
& VT_VALMASK
;
4742 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
))
4744 /* also look at second register (if long long) */
4745 r
= p
->r2
& VT_VALMASK
;
4746 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
4752 /* Should never comes here */
4756 /* save registers up to (vtop - n) stack entry */
4757 void save_regs(int n
)
4762 for(p
= vstack
;p
<= p1
; p
++) {
4763 r
= p
->r
& VT_VALMASK
;
4770 /* move register 's' to 'r', and flush previous value of r to memory
4772 void move_reg(int r
, int s
)
4785 /* get address of vtop (vtop MUST BE an lvalue) */
4788 vtop
->r
&= ~VT_LVAL
;
4789 /* tricky: if saved lvalue, then we can go back to lvalue */
4790 if ((vtop
->r
& VT_VALMASK
) == VT_LLOCAL
)
4791 vtop
->r
= (vtop
->r
& ~(VT_VALMASK
| VT_LVAL_TYPE
)) | VT_LOCAL
| VT_LVAL
;
4794 #ifdef CONFIG_TCC_BCHECK
4795 /* generate lvalue bound code */
4801 vtop
->r
&= ~VT_MUSTBOUND
;
4802 /* if lvalue, then use checking code before dereferencing */
4803 if (vtop
->r
& VT_LVAL
) {
4804 /* if not VT_BOUNDED value, then make one */
4805 if (!(vtop
->r
& VT_BOUNDED
)) {
4806 lval_type
= vtop
->r
& (VT_LVAL_TYPE
| VT_LVAL
);
4807 /* must save type because we must set it to int to get pointer */
4809 vtop
->type
.t
= VT_INT
;
4812 gen_bounded_ptr_add();
4813 vtop
->r
|= lval_type
;
4816 /* then check for dereferencing */
4817 gen_bounded_ptr_deref();
4822 /* store vtop a register belonging to class 'rc'. lvalues are
4823 converted to values. Cannot be used if cannot be converted to
4824 register value (such as structures). */
4827 int r
, r2
, rc2
, bit_pos
, bit_size
, size
, align
, i
;
4828 unsigned long long ll
;
4830 /* NOTE: get_reg can modify vstack[] */
4831 if (vtop
->type
.t
& VT_BITFIELD
) {
4832 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
4833 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
4834 /* remove bit field info to avoid loops */
4835 vtop
->type
.t
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
4836 /* generate shifts */
4837 vpushi(32 - (bit_pos
+ bit_size
));
4839 vpushi(32 - bit_size
);
4840 /* NOTE: transformed to SHR if unsigned */
4844 if (is_float(vtop
->type
.t
) &&
4845 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4848 unsigned long offset
;
4849 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4853 /* XXX: unify with initializers handling ? */
4854 /* CPUs usually cannot use float constants, so we store them
4855 generically in data segment */
4856 size
= type_size(&vtop
->type
, &align
);
4857 offset
= (data_section
->data_offset
+ align
- 1) & -align
;
4858 data_section
->data_offset
= offset
;
4859 /* XXX: not portable yet */
4861 /* Zero pad x87 tenbyte long doubles */
4863 vtop
->c
.tab
[2] &= 0xffff;
4865 ptr
= section_ptr_add(data_section
, size
);
4867 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4871 ptr
[i
] = vtop
->c
.tab
[size
-1-i
];
4875 ptr
[i
] = vtop
->c
.tab
[i
];
4876 sym
= get_sym_ref(&vtop
->type
, data_section
, offset
, size
<< 2);
4877 vtop
->r
|= VT_LVAL
| VT_SYM
;
4881 #ifdef CONFIG_TCC_BCHECK
4882 if (vtop
->r
& VT_MUSTBOUND
)
4886 r
= vtop
->r
& VT_VALMASK
;
4887 /* need to reload if:
4889 - lvalue (need to dereference pointer)
4890 - already a register, but not in the right class */
4891 if (r
>= VT_CONST
||
4892 (vtop
->r
& VT_LVAL
) ||
4893 !(reg_classes
[r
] & rc
) ||
4894 ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
&&
4895 !(reg_classes
[vtop
->r2
] & rc
))) {
4897 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
4898 /* two register type load : expand to two words
4900 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4903 vtop
->c
.ui
= ll
; /* first word */
4905 vtop
->r
= r
; /* save register value */
4906 vpushi(ll
>> 32); /* second word */
4907 } else if (r
>= VT_CONST
|| /* XXX: test to VT_CONST incorrect ? */
4908 (vtop
->r
& VT_LVAL
)) {
4909 /* We do not want to modifier the long long
4910 pointer here, so the safest (and less
4911 efficient) is to save all the other registers
4912 in the stack. XXX: totally inefficient. */
4914 /* load from memory */
4917 vtop
[-1].r
= r
; /* save register value */
4918 /* increment pointer to get second word */
4919 vtop
->type
.t
= VT_INT
;
4925 /* move registers */
4928 vtop
[-1].r
= r
; /* save register value */
4929 vtop
->r
= vtop
[-1].r2
;
4931 /* allocate second register */
4938 /* write second register */
4940 } else if ((vtop
->r
& VT_LVAL
) && !is_float(vtop
->type
.t
)) {
4942 /* lvalue of scalar type : need to use lvalue type
4943 because of possible cast */
4946 /* compute memory access type */
4947 if (vtop
->r
& VT_LVAL_BYTE
)
4949 else if (vtop
->r
& VT_LVAL_SHORT
)
4951 if (vtop
->r
& VT_LVAL_UNSIGNED
)
4955 /* restore wanted type */
4958 /* one register type load */
4963 #ifdef TCC_TARGET_C67
4964 /* uses register pairs for doubles */
4965 if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
)
4972 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4973 void gv2(int rc1
, int rc2
)
4977 /* generate more generic register first. But VT_JMP or VT_CMP
4978 values must be generated first in all cases to avoid possible
4980 v
= vtop
[0].r
& VT_VALMASK
;
4981 if (v
!= VT_CMP
&& (v
& ~1) != VT_JMP
&& rc1
<= rc2
) {
4986 /* test if reload is needed for first register */
4987 if ((vtop
[-1].r
& VT_VALMASK
) >= VT_CONST
) {
4997 /* test if reload is needed for first register */
4998 if ((vtop
[0].r
& VT_VALMASK
) >= VT_CONST
) {
5004 /* expand long long on stack in two int registers */
5009 u
= vtop
->type
.t
& VT_UNSIGNED
;
5012 vtop
[0].r
= vtop
[-1].r2
;
5013 vtop
[0].r2
= VT_CONST
;
5014 vtop
[-1].r2
= VT_CONST
;
5015 vtop
[0].type
.t
= VT_INT
| u
;
5016 vtop
[-1].type
.t
= VT_INT
| u
;
5019 #ifdef TCC_TARGET_ARM
5020 /* expand long long on stack */
5021 void lexpand_nr(void)
5025 u
= vtop
->type
.t
& VT_UNSIGNED
;
5027 vtop
->r2
= VT_CONST
;
5028 vtop
->type
.t
= VT_INT
| u
;
5029 v
=vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
);
5030 if (v
== VT_CONST
) {
5031 vtop
[-1].c
.ui
= vtop
->c
.ull
;
5032 vtop
->c
.ui
= vtop
->c
.ull
>> 32;
5034 } else if (v
== (VT_LVAL
|VT_CONST
) || v
== (VT_LVAL
|VT_LOCAL
)) {
5036 vtop
->r
= vtop
[-1].r
;
5037 } else if (v
> VT_CONST
) {
5041 vtop
->r
= vtop
[-1].r2
;
5042 vtop
[-1].r2
= VT_CONST
;
5043 vtop
[-1].type
.t
= VT_INT
| u
;
5047 /* build a long long from two ints */
5050 gv2(RC_INT
, RC_INT
);
5051 vtop
[-1].r2
= vtop
[0].r
;
5052 vtop
[-1].type
.t
= t
;
5056 /* rotate n first stack elements to the bottom
5057 I1 ... In -> I2 ... In I1 [top is right]
5065 for(i
=-n
+1;i
!=0;i
++)
5066 vtop
[i
] = vtop
[i
+1];
5070 /* rotate n first stack elements to the top
5071 I1 ... In -> In I1 ... I(n-1) [top is right]
5079 for(i
= 0;i
< n
- 1; i
++)
5080 vtop
[-i
] = vtop
[-i
- 1];
5084 #ifdef TCC_TARGET_ARM
5085 /* like vrott but in other direction
5086 In ... I1 -> I(n-1) ... I1 In [top is right]
5094 for(i
= n
- 1; i
> 0; i
--)
5095 vtop
[-i
] = vtop
[-i
+ 1];
5100 /* pop stack value */
5104 v
= vtop
->r
& VT_VALMASK
;
5105 #ifdef TCC_TARGET_I386
5106 /* for x86, we need to pop the FP stack */
5107 if (v
== TREG_ST0
&& !nocode_wanted
) {
5108 o(0xd9dd); /* fstp %st(1) */
5111 if (v
== VT_JMP
|| v
== VT_JMPI
) {
5112 /* need to put correct jump if && or || without test */
5118 /* convert stack entry to register and duplicate its value in another
5126 if ((t
& VT_BTYPE
) == VT_LLONG
) {
5133 /* stack: H L L1 H1 */
5141 /* duplicate value */
5152 load(r1
, &sv
); /* move r to r1 */
5154 /* duplicates value */
5159 /* generate CPU independent (unsigned) long long operations */
5160 void gen_opl(int op
)
5162 int t
, a
, b
, op1
, c
, i
;
5169 func
= TOK___divdi3
;
5172 func
= TOK___udivdi3
;
5175 func
= TOK___moddi3
;
5178 func
= TOK___umoddi3
;
5180 /* call generic long long function */
5181 vpush_global_sym(&func_old_type
, func
);
5186 vtop
->r2
= REG_LRET
;
5199 /* stack: L1 H1 L2 H2 */
5204 vtop
[-2] = vtop
[-3];
5207 /* stack: H1 H2 L1 L2 */
5213 /* stack: H1 H2 L1 L2 ML MH */
5216 /* stack: ML MH H1 H2 L1 L2 */
5220 /* stack: ML MH H1 L2 H2 L1 */
5225 /* stack: ML MH M1 M2 */
5228 } else if (op
== '+' || op
== '-') {
5229 /* XXX: add non carry method too (for MIPS or alpha) */
5235 /* stack: H1 H2 (L1 op L2) */
5238 gen_op(op1
+ 1); /* TOK_xxxC2 */
5241 /* stack: H1 H2 (L1 op L2) */
5244 /* stack: (L1 op L2) H1 H2 */
5246 /* stack: (L1 op L2) (H1 op H2) */
5254 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
5255 t
= vtop
[-1].type
.t
;
5259 /* stack: L H shift */
5261 /* constant: simpler */
5262 /* NOTE: all comments are for SHL. the other cases are
5263 done by swaping words */
5274 if (op
!= TOK_SAR
) {
5307 /* XXX: should provide a faster fallback on x86 ? */
5310 func
= TOK___sardi3
;
5313 func
= TOK___shrdi3
;
5316 func
= TOK___shldi3
;
5322 /* compare operations */
5328 /* stack: L1 H1 L2 H2 */
5330 vtop
[-1] = vtop
[-2];
5332 /* stack: L1 L2 H1 H2 */
5335 /* when values are equal, we need to compare low words. since
5336 the jump is inverted, we invert the test too. */
5339 else if (op1
== TOK_GT
)
5341 else if (op1
== TOK_ULT
)
5343 else if (op1
== TOK_UGT
)
5348 if (op1
!= TOK_NE
) {
5352 /* generate non equal test */
5353 /* XXX: NOT PORTABLE yet */
5357 #if defined(TCC_TARGET_I386)
5358 b
= psym(0x850f, 0);
5359 #elif defined(TCC_TARGET_ARM)
5361 o(0x1A000000 | encbranch(ind
, 0, 1));
5362 #elif defined(TCC_TARGET_C67)
5363 error("not implemented");
5365 #error not supported
5369 /* compare low. Always unsigned */
5373 else if (op1
== TOK_LE
)
5375 else if (op1
== TOK_GT
)
5377 else if (op1
== TOK_GE
)
5387 /* handle integer constant optimizations and various machine
5389 void gen_opic(int op
)
5391 int c1
, c2
, t1
, t2
, n
, c
;
5393 long long l1
, l2
, l
;
5394 typedef unsigned long long U
;
5398 t1
= v1
->type
.t
& VT_BTYPE
;
5399 t2
= v2
->type
.t
& VT_BTYPE
;
5400 l1
= (t1
== VT_LLONG
) ? v1
->c
.ll
: v1
->c
.i
;
5401 l2
= (t2
== VT_LLONG
) ? v2
->c
.ll
: v2
->c
.i
;
5403 /* currently, we cannot do computations with forward symbols */
5404 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5405 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5408 case '+': l1
+= l2
; break;
5409 case '-': l1
-= l2
; break;
5410 case '&': l1
&= l2
; break;
5411 case '^': l1
^= l2
; break;
5412 case '|': l1
|= l2
; break;
5413 case '*': l1
*= l2
; break;
5420 /* if division by zero, generate explicit division */
5423 error("division by zero in constant");
5427 default: l1
/= l2
; break;
5428 case '%': l1
%= l2
; break;
5429 case TOK_UDIV
: l1
= (U
)l1
/ l2
; break;
5430 case TOK_UMOD
: l1
= (U
)l1
% l2
; break;
5433 case TOK_SHL
: l1
<<= l2
; break;
5434 case TOK_SHR
: l1
= (U
)l1
>> l2
; break;
5435 case TOK_SAR
: l1
>>= l2
; break;
5437 case TOK_ULT
: l1
= (U
)l1
< (U
)l2
; break;
5438 case TOK_UGE
: l1
= (U
)l1
>= (U
)l2
; break;
5439 case TOK_EQ
: l1
= l1
== l2
; break;
5440 case TOK_NE
: l1
= l1
!= l2
; break;
5441 case TOK_ULE
: l1
= (U
)l1
<= (U
)l2
; break;
5442 case TOK_UGT
: l1
= (U
)l1
> (U
)l2
; break;
5443 case TOK_LT
: l1
= l1
< l2
; break;
5444 case TOK_GE
: l1
= l1
>= l2
; break;
5445 case TOK_LE
: l1
= l1
<= l2
; break;
5446 case TOK_GT
: l1
= l1
> l2
; break;
5448 case TOK_LAND
: l1
= l1
&& l2
; break;
5449 case TOK_LOR
: l1
= l1
|| l2
; break;
5456 /* if commutative ops, put c2 as constant */
5457 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
5458 op
== '|' || op
== '*')) {
5460 c
= c1
, c1
= c2
, c2
= c
;
5461 l
= l1
, l1
= l2
, l2
= l
;
5463 /* Filter out NOP operations like x*1, x-0, x&-1... */
5464 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
5467 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
5468 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
5474 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
5475 /* try to use shifts instead of muls or divs */
5476 if (l2
> 0 && (l2
& (l2
- 1)) == 0) {
5485 else if (op
== TOK_PDIV
)
5491 } else if (c2
&& (op
== '+' || op
== '-') &&
5492 (vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) ==
5493 (VT_CONST
| VT_SYM
)) {
5494 /* symbol + constant case */
5501 if (!nocode_wanted
) {
5502 /* call low level op generator */
5503 if (t1
== VT_LLONG
|| t2
== VT_LLONG
)
5514 /* generate a floating point operation with constant propagation */
5515 void gen_opif(int op
)
5523 /* currently, we cannot do computations with forward symbols */
5524 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5525 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5527 if (v1
->type
.t
== VT_FLOAT
) {
5530 } else if (v1
->type
.t
== VT_DOUBLE
) {
5538 /* NOTE: we only do constant propagation if finite number (not
5539 NaN or infinity) (ANSI spec) */
5540 if (!ieee_finite(f1
) || !ieee_finite(f2
))
5544 case '+': f1
+= f2
; break;
5545 case '-': f1
-= f2
; break;
5546 case '*': f1
*= f2
; break;
5550 error("division by zero in constant");
5555 /* XXX: also handles tests ? */
5559 /* XXX: overflow test ? */
5560 if (v1
->type
.t
== VT_FLOAT
) {
5562 } else if (v1
->type
.t
== VT_DOUBLE
) {
5570 if (!nocode_wanted
) {
5578 static int pointed_size(CType
*type
)
5581 return type_size(pointed_type(type
), &align
);
5584 static inline int is_null_pointer(SValue
*p
)
5586 if ((p
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
5588 return ((p
->type
.t
& VT_BTYPE
) == VT_INT
&& p
->c
.i
== 0) ||
5589 ((p
->type
.t
& VT_BTYPE
) == VT_LLONG
&& p
->c
.ll
== 0);
5592 static inline int is_integer_btype(int bt
)
5594 return (bt
== VT_BYTE
|| bt
== VT_SHORT
||
5595 bt
== VT_INT
|| bt
== VT_LLONG
);
5598 /* check types for comparison or substraction of pointers */
5599 static void check_comparison_pointer_types(SValue
*p1
, SValue
*p2
, int op
)
5601 CType
*type1
, *type2
, tmp_type1
, tmp_type2
;
5604 /* null pointers are accepted for all comparisons as gcc */
5605 if (is_null_pointer(p1
) || is_null_pointer(p2
))
5609 bt1
= type1
->t
& VT_BTYPE
;
5610 bt2
= type2
->t
& VT_BTYPE
;
5611 /* accept comparison between pointer and integer with a warning */
5612 if ((is_integer_btype(bt1
) || is_integer_btype(bt2
)) && op
!= '-') {
5613 if (op
!= TOK_LOR
&& op
!= TOK_LAND
)
5614 warning("comparison between pointer and integer");
5618 /* both must be pointers or implicit function pointers */
5619 if (bt1
== VT_PTR
) {
5620 type1
= pointed_type(type1
);
5621 } else if (bt1
!= VT_FUNC
)
5622 goto invalid_operands
;
5624 if (bt2
== VT_PTR
) {
5625 type2
= pointed_type(type2
);
5626 } else if (bt2
!= VT_FUNC
) {
5628 error("invalid operands to binary %s", get_tok_str(op
, NULL
));
5630 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
5631 (type2
->t
& VT_BTYPE
) == VT_VOID
)
5635 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5636 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5637 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
5638 /* gcc-like error if '-' is used */
5640 goto invalid_operands
;
5642 warning("comparison of distinct pointer types lacks a cast");
5646 /* generic gen_op: handles types problems */
5649 int u
, t1
, t2
, bt1
, bt2
, t
;
5652 t1
= vtop
[-1].type
.t
;
5653 t2
= vtop
[0].type
.t
;
5654 bt1
= t1
& VT_BTYPE
;
5655 bt2
= t2
& VT_BTYPE
;
5657 if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
5658 /* at least one operand is a pointer */
5659 /* relationnal op: must be both pointers */
5660 if (op
>= TOK_ULT
&& op
<= TOK_LOR
) {
5661 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5662 /* pointers are handled are unsigned */
5663 t
= VT_INT
| VT_UNSIGNED
;
5666 /* if both pointers, then it must be the '-' op */
5667 if (bt1
== VT_PTR
&& bt2
== VT_PTR
) {
5669 error("cannot use pointers here");
5670 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5671 /* XXX: check that types are compatible */
5672 u
= pointed_size(&vtop
[-1].type
);
5674 /* set to integer type */
5675 vtop
->type
.t
= VT_INT
;
5679 /* exactly one pointer : must be '+' or '-'. */
5680 if (op
!= '-' && op
!= '+')
5681 error("cannot use pointers here");
5682 /* Put pointer as first operand */
5683 if (bt2
== VT_PTR
) {
5687 type1
= vtop
[-1].type
;
5688 /* XXX: cast to int ? (long long case) */
5689 vpushi(pointed_size(&vtop
[-1].type
));
5691 #ifdef CONFIG_TCC_BCHECK
5692 /* if evaluating constant expression, no code should be
5693 generated, so no bound check */
5694 if (do_bounds_check
&& !const_wanted
) {
5695 /* if bounded pointers, we generate a special code to
5702 gen_bounded_ptr_add();
5708 /* put again type if gen_opic() swaped operands */
5711 } else if (is_float(bt1
) || is_float(bt2
)) {
5712 /* compute bigger type and do implicit casts */
5713 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
5715 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
5720 /* floats can only be used for a few operations */
5721 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
5722 (op
< TOK_ULT
|| op
> TOK_GT
))
5723 error("invalid operands for binary operation");
5725 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
5726 /* cast to biggest op */
5728 /* convert to unsigned if it does not fit in a long long */
5729 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
5730 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
5734 /* integer operations */
5736 /* convert to unsigned if it does not fit in an integer */
5737 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
5738 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
5741 /* XXX: currently, some unsigned operations are explicit, so
5742 we modify them here */
5743 if (t
& VT_UNSIGNED
) {
5750 else if (op
== TOK_LT
)
5752 else if (op
== TOK_GT
)
5754 else if (op
== TOK_LE
)
5756 else if (op
== TOK_GE
)
5763 /* special case for shifts and long long: we keep the shift as
5765 if (op
== TOK_SHR
|| op
== TOK_SAR
|| op
== TOK_SHL
)
5772 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
5773 /* relationnal op: the result is an int */
5774 vtop
->type
.t
= VT_INT
;
5781 /* generic itof for unsigned long long case */
5782 void gen_cvt_itof1(int t
)
5784 if ((vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
)) ==
5785 (VT_LLONG
| VT_UNSIGNED
)) {
5788 vpush_global_sym(&func_old_type
, TOK___ulltof
);
5789 else if (t
== VT_DOUBLE
)
5790 vpush_global_sym(&func_old_type
, TOK___ulltod
);
5792 vpush_global_sym(&func_old_type
, TOK___ulltold
);
5802 /* generic ftoi for unsigned long long case */
5803 void gen_cvt_ftoi1(int t
)
5807 if (t
== (VT_LLONG
| VT_UNSIGNED
)) {
5808 /* not handled natively */
5809 st
= vtop
->type
.t
& VT_BTYPE
;
5811 vpush_global_sym(&func_old_type
, TOK___fixunssfdi
);
5812 else if (st
== VT_DOUBLE
)
5813 vpush_global_sym(&func_old_type
, TOK___fixunsdfdi
);
5815 vpush_global_sym(&func_old_type
, TOK___fixunsxfdi
);
5820 vtop
->r2
= REG_LRET
;
5826 /* force char or short cast */
5827 void force_charshort_cast(int t
)
5831 /* XXX: add optimization if lvalue : just change type and offset */
5836 if (t
& VT_UNSIGNED
) {
5837 vpushi((1 << bits
) - 1);
5843 /* result must be signed or the SAR is converted to an SHL
5844 This was not the case when "t" was a signed short
5845 and the last value on the stack was an unsigned int */
5846 vtop
->type
.t
&= ~VT_UNSIGNED
;
5852 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5853 static void gen_cast(CType
*type
)
5855 int sbt
, dbt
, sf
, df
, c
;
5857 /* special delayed cast for char/short */
5858 /* XXX: in some cases (multiple cascaded casts), it may still
5860 if (vtop
->r
& VT_MUSTCAST
) {
5861 vtop
->r
&= ~VT_MUSTCAST
;
5862 force_charshort_cast(vtop
->type
.t
);
5865 /* bitfields first get cast to ints */
5866 if (vtop
->type
.t
& VT_BITFIELD
) {
5870 dbt
= type
->t
& (VT_BTYPE
| VT_UNSIGNED
);
5871 sbt
= vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
);
5873 if (sbt
!= dbt
&& !nocode_wanted
) {
5876 c
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5878 /* convert from fp to fp */
5880 /* constant case: we can do it now */
5881 /* XXX: in ISOC, cannot do it if error in convert */
5882 if (dbt
== VT_FLOAT
&& sbt
== VT_DOUBLE
)
5883 vtop
->c
.f
= (float)vtop
->c
.d
;
5884 else if (dbt
== VT_FLOAT
&& sbt
== VT_LDOUBLE
)
5885 vtop
->c
.f
= (float)vtop
->c
.ld
;
5886 else if (dbt
== VT_DOUBLE
&& sbt
== VT_FLOAT
)
5887 vtop
->c
.d
= (double)vtop
->c
.f
;
5888 else if (dbt
== VT_DOUBLE
&& sbt
== VT_LDOUBLE
)
5889 vtop
->c
.d
= (double)vtop
->c
.ld
;
5890 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_FLOAT
)
5891 vtop
->c
.ld
= (long double)vtop
->c
.f
;
5892 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_DOUBLE
)
5893 vtop
->c
.ld
= (long double)vtop
->c
.d
;
5895 /* non constant case: generate code */
5899 /* convert int to fp */
5902 case VT_LLONG
| VT_UNSIGNED
:
5904 /* XXX: add const cases for long long */
5906 case VT_INT
| VT_UNSIGNED
:
5908 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.ui
; break;
5909 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.ui
; break;
5910 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.ui
; break;
5915 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.i
; break;
5916 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.i
; break;
5917 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.i
; break;
5923 #if !defined(TCC_TARGET_ARM)
5930 /* convert fp to int */
5931 if (dbt
== VT_BOOL
) {
5935 /* we handle char/short/etc... with generic code */
5936 if (dbt
!= (VT_INT
| VT_UNSIGNED
) &&
5937 dbt
!= (VT_LLONG
| VT_UNSIGNED
) &&
5942 case VT_LLONG
| VT_UNSIGNED
:
5944 /* XXX: add const cases for long long */
5946 case VT_INT
| VT_UNSIGNED
:
5948 case VT_FLOAT
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5949 case VT_DOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5950 case VT_LDOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5956 case VT_FLOAT
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5957 case VT_DOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5958 case VT_LDOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5966 if (dbt
== VT_INT
&& (type
->t
& (VT_BTYPE
| VT_UNSIGNED
)) != dbt
) {
5967 /* additional cast for char/short... */
5972 } else if ((dbt
& VT_BTYPE
) == VT_LLONG
) {
5973 if ((sbt
& VT_BTYPE
) != VT_LLONG
) {
5974 /* scalar to long long */
5976 if (sbt
== (VT_INT
| VT_UNSIGNED
))
5977 vtop
->c
.ll
= vtop
->c
.ui
;
5979 vtop
->c
.ll
= vtop
->c
.i
;
5981 /* machine independent conversion */
5983 /* generate high word */
5984 if (sbt
== (VT_INT
| VT_UNSIGNED
)) {
5992 /* patch second register */
5993 vtop
[-1].r2
= vtop
->r
;
5997 } else if (dbt
== VT_BOOL
) {
5998 /* scalar to bool */
6001 } else if ((dbt
& VT_BTYPE
) == VT_BYTE
||
6002 (dbt
& VT_BTYPE
) == VT_SHORT
) {
6003 if (sbt
== VT_PTR
) {
6004 vtop
->type
.t
= VT_INT
;
6005 warning("nonportable conversion from pointer to char/short");
6007 force_charshort_cast(dbt
);
6008 } else if ((dbt
& VT_BTYPE
) == VT_INT
) {
6010 if (sbt
== VT_LLONG
) {
6011 /* from long long: just take low order word */
6015 /* if lvalue and single word type, nothing to do because
6016 the lvalue already contains the real type size (see
6017 VT_LVAL_xxx constants) */
6019 } else if ((dbt
& VT_BTYPE
) == VT_PTR
&& !(vtop
->r
& VT_LVAL
)) {
6020 /* if we are casting between pointer types,
6021 we must update the VT_LVAL_xxx size */
6022 vtop
->r
= (vtop
->r
& ~VT_LVAL_TYPE
)
6023 | (lvalue_type(type
->ref
->type
.t
) & VT_LVAL_TYPE
);
6028 /* return type size. Put alignment at 'a' */
6029 static int type_size(CType
*type
, int *a
)
6034 bt
= type
->t
& VT_BTYPE
;
6035 if (bt
== VT_STRUCT
) {
6040 } else if (bt
== VT_PTR
) {
6041 if (type
->t
& VT_ARRAY
) {
6043 return type_size(&s
->type
, a
) * s
->c
;
6048 } else if (bt
== VT_LDOUBLE
) {
6050 return LDOUBLE_SIZE
;
6051 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
6052 #ifdef TCC_TARGET_I386
6054 #elif defined(TCC_TARGET_ARM)
6064 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
6067 } else if (bt
== VT_SHORT
) {
6071 /* char, void, function, _Bool */
6077 /* return the pointed type of t */
6078 static inline CType
*pointed_type(CType
*type
)
6080 return &type
->ref
->type
;
6083 /* modify type so that its it is a pointer to type. */
6084 static void mk_pointer(CType
*type
)
6087 s
= sym_push(SYM_FIELD
, type
, 0, -1);
6088 type
->t
= VT_PTR
| (type
->t
& ~VT_TYPE
);
6092 /* compare function types. OLD functions match any new functions */
6093 static int is_compatible_func(CType
*type1
, CType
*type2
)
6099 if (!is_compatible_types(&s1
->type
, &s2
->type
))
6101 /* check func_call */
6104 /* XXX: not complete */
6105 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
6109 while (s1
!= NULL
) {
6112 if (!is_compatible_parameter_types(&s1
->type
, &s2
->type
))
6122 /* return true if type1 and type2 are the same. If unqualified is
6123 true, qualifiers on the types are ignored.
6125 - enums are not checked as gcc __builtin_types_compatible_p ()
6127 static int compare_types(CType
*type1
, CType
*type2
, int unqualified
)
6131 t1
= type1
->t
& VT_TYPE
;
6132 t2
= type2
->t
& VT_TYPE
;
6134 /* strip qualifiers before comparing */
6135 t1
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6136 t2
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6138 /* XXX: bitfields ? */
6141 /* test more complicated cases */
6142 bt1
= t1
& VT_BTYPE
;
6143 if (bt1
== VT_PTR
) {
6144 type1
= pointed_type(type1
);
6145 type2
= pointed_type(type2
);
6146 return is_compatible_types(type1
, type2
);
6147 } else if (bt1
== VT_STRUCT
) {
6148 return (type1
->ref
== type2
->ref
);
6149 } else if (bt1
== VT_FUNC
) {
6150 return is_compatible_func(type1
, type2
);
6156 /* return true if type1 and type2 are exactly the same (including
6159 static int is_compatible_types(CType
*type1
, CType
*type2
)
6161 return compare_types(type1
,type2
,0);
6164 /* return true if type1 and type2 are the same (ignoring qualifiers).
6166 static int is_compatible_parameter_types(CType
*type1
, CType
*type2
)
6168 return compare_types(type1
,type2
,1);
6171 /* print a type. If 'varstr' is not NULL, then the variable is also
6172 printed in the type */
6174 /* XXX: add array and function pointers */
6175 void type_to_str(char *buf
, int buf_size
,
6176 CType
*type
, const char *varstr
)
6183 t
= type
->t
& VT_TYPE
;
6186 if (t
& VT_CONSTANT
)
6187 pstrcat(buf
, buf_size
, "const ");
6188 if (t
& VT_VOLATILE
)
6189 pstrcat(buf
, buf_size
, "volatile ");
6190 if (t
& VT_UNSIGNED
)
6191 pstrcat(buf
, buf_size
, "unsigned ");
6221 tstr
= "long double";
6223 pstrcat(buf
, buf_size
, tstr
);
6227 if (bt
== VT_STRUCT
)
6231 pstrcat(buf
, buf_size
, tstr
);
6232 v
= type
->ref
->v
& ~SYM_STRUCT
;
6233 if (v
>= SYM_FIRST_ANOM
)
6234 pstrcat(buf
, buf_size
, "<anonymous>");
6236 pstrcat(buf
, buf_size
, get_tok_str(v
, NULL
));
6240 type_to_str(buf
, buf_size
, &s
->type
, varstr
);
6241 pstrcat(buf
, buf_size
, "(");
6243 while (sa
!= NULL
) {
6244 type_to_str(buf1
, sizeof(buf1
), &sa
->type
, NULL
);
6245 pstrcat(buf
, buf_size
, buf1
);
6248 pstrcat(buf
, buf_size
, ", ");
6250 pstrcat(buf
, buf_size
, ")");
6254 pstrcpy(buf1
, sizeof(buf1
), "*");
6256 pstrcat(buf1
, sizeof(buf1
), varstr
);
6257 type_to_str(buf
, buf_size
, &s
->type
, buf1
);
6261 pstrcat(buf
, buf_size
, " ");
6262 pstrcat(buf
, buf_size
, varstr
);
6267 /* verify type compatibility to store vtop in 'dt' type, and generate
6269 static void gen_assign_cast(CType
*dt
)
6271 CType
*st
, *type1
, *type2
, tmp_type1
, tmp_type2
;
6272 char buf1
[256], buf2
[256];
6275 st
= &vtop
->type
; /* source type */
6276 dbt
= dt
->t
& VT_BTYPE
;
6277 sbt
= st
->t
& VT_BTYPE
;
6278 if (dt
->t
& VT_CONSTANT
)
6279 warning("assignment of read-only location");
6282 /* special cases for pointers */
6283 /* '0' can also be a pointer */
6284 if (is_null_pointer(vtop
))
6286 /* accept implicit pointer to integer cast with warning */
6287 if (is_integer_btype(sbt
)) {
6288 warning("assignment makes pointer from integer without a cast");
6291 type1
= pointed_type(dt
);
6292 /* a function is implicitely a function pointer */
6293 if (sbt
== VT_FUNC
) {
6294 if ((type1
->t
& VT_BTYPE
) != VT_VOID
&&
6295 !is_compatible_types(pointed_type(dt
), st
))
6302 type2
= pointed_type(st
);
6303 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
6304 (type2
->t
& VT_BTYPE
) == VT_VOID
) {
6305 /* void * can match anything */
6307 /* exact type match, except for unsigned */
6310 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6311 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6312 if (!is_compatible_types(&tmp_type1
, &tmp_type2
))
6313 warning("assignment from incompatible pointer type");
6315 /* check const and volatile */
6316 if ((!(type1
->t
& VT_CONSTANT
) && (type2
->t
& VT_CONSTANT
)) ||
6317 (!(type1
->t
& VT_VOLATILE
) && (type2
->t
& VT_VOLATILE
)))
6318 warning("assignment discards qualifiers from pointer target type");
6324 if (sbt
== VT_PTR
|| sbt
== VT_FUNC
) {
6325 warning("assignment makes integer from pointer without a cast");
6327 /* XXX: more tests */
6332 tmp_type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6333 tmp_type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6334 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
6336 type_to_str(buf1
, sizeof(buf1
), st
, NULL
);
6337 type_to_str(buf2
, sizeof(buf2
), dt
, NULL
);
6338 error("cannot cast '%s' to '%s'", buf1
, buf2
);
6346 /* store vtop in lvalue pushed on stack */
6349 int sbt
, dbt
, ft
, r
, t
, size
, align
, bit_size
, bit_pos
, rc
, delayed_cast
;
6351 ft
= vtop
[-1].type
.t
;
6352 sbt
= vtop
->type
.t
& VT_BTYPE
;
6353 dbt
= ft
& VT_BTYPE
;
6354 if (((sbt
== VT_INT
|| sbt
== VT_SHORT
) && dbt
== VT_BYTE
) ||
6355 (sbt
== VT_INT
&& dbt
== VT_SHORT
)) {
6356 /* optimize char/short casts */
6357 delayed_cast
= VT_MUSTCAST
;
6358 vtop
->type
.t
= ft
& VT_TYPE
;
6359 /* XXX: factorize */
6360 if (ft
& VT_CONSTANT
)
6361 warning("assignment of read-only location");
6364 if (!(ft
& VT_BITFIELD
))
6365 gen_assign_cast(&vtop
[-1].type
);
6368 if (sbt
== VT_STRUCT
) {
6369 /* if structure, only generate pointer */
6370 /* structure assignment : generate memcpy */
6371 /* XXX: optimize if small size */
6372 if (!nocode_wanted
) {
6373 size
= type_size(&vtop
->type
, &align
);
6377 vpush_global_sym(&func_old_type
, TOK_memcpy8
);
6378 else if(!(align
& 3))
6379 vpush_global_sym(&func_old_type
, TOK_memcpy4
);
6382 vpush_global_sym(&func_old_type
, TOK_memcpy
);
6386 vtop
->type
.t
= VT_INT
;
6390 vtop
->type
.t
= VT_INT
;
6402 /* leave source on stack */
6403 } else if (ft
& VT_BITFIELD
) {
6404 /* bitfield store handling */
6405 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
6406 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
6407 /* remove bit field info to avoid loops */
6408 vtop
[-1].type
.t
= ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
6410 /* duplicate source into other register */
6415 /* duplicate destination */
6417 vtop
[-1] = vtop
[-2];
6419 /* mask and shift source */
6420 vpushi((1 << bit_size
) - 1);
6424 /* load destination, mask and or with source */
6426 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
6432 /* pop off shifted source from "duplicate source..." above */
6436 #ifdef CONFIG_TCC_BCHECK
6437 /* bound check case */
6438 if (vtop
[-1].r
& VT_MUSTBOUND
) {
6444 if (!nocode_wanted
) {
6448 r
= gv(rc
); /* generate value */
6449 /* if lvalue was saved on stack, must read it */
6450 if ((vtop
[-1].r
& VT_VALMASK
) == VT_LLOCAL
) {
6452 t
= get_reg(RC_INT
);
6454 sv
.r
= VT_LOCAL
| VT_LVAL
;
6455 sv
.c
.ul
= vtop
[-1].c
.ul
;
6457 vtop
[-1].r
= t
| VT_LVAL
;
6460 /* two word case handling : store second register at word + 4 */
6461 if ((ft
& VT_BTYPE
) == VT_LLONG
) {
6463 /* convert to int to increment easily */
6464 vtop
->type
.t
= VT_INT
;
6470 /* XXX: it works because r2 is spilled last ! */
6471 store(vtop
->r2
, vtop
- 1);
6475 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
6476 vtop
->r
|= delayed_cast
;
6480 /* post defines POST/PRE add. c is the token ++ or -- */
6481 void inc(int post
, int c
)
6484 vdup(); /* save lvalue */
6486 gv_dup(); /* duplicate value */
6491 vpushi(c
- TOK_MID
);
6493 vstore(); /* store value */
6495 vpop(); /* if post op, return saved value */
6498 /* Parse GNUC __attribute__ extension. Currently, the following
6499 extensions are recognized:
6500 - aligned(n) : set data/function alignment.
6501 - packed : force data alignment to 1
6502 - section(x) : generate data/code in this section.
6503 - unused : currently ignored, but may be used someday.
6504 - regparm(n) : pass function parameters in registers (i386 only)
6506 static void parse_attribute(AttributeDef
*ad
)
6510 while (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
) {
6514 while (tok
!= ')') {
6515 if (tok
< TOK_IDENT
)
6516 expect("attribute name");
6524 expect("section name");
6525 ad
->section
= find_section(tcc_state
, (char *)tokc
.cstr
->data
);
6534 if (n
<= 0 || (n
& (n
- 1)) != 0)
6535 error("alignment must be a positive power of two");
6548 /* currently, no need to handle it because tcc does not
6549 track unused objects */
6553 /* currently, no need to handle it because tcc does not
6554 track unused objects */
6559 ad
->func_call
= FUNC_CDECL
;
6564 ad
->func_call
= FUNC_STDCALL
;
6566 #ifdef TCC_TARGET_I386
6576 ad
->func_call
= FUNC_FASTCALL1
+ n
- 1;
6582 ad
->func_call
= FUNC_FASTCALLW
;
6589 if (tcc_state
->warn_unsupported
)
6590 warning("'%s' attribute ignored", get_tok_str(t
, NULL
));
6591 /* skip parameters */
6593 int parenthesis
= 0;
6597 else if (tok
== ')')
6600 } while (parenthesis
&& tok
!= -1);
6613 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6614 static void struct_decl(CType
*type
, int u
)
6616 int a
, v
, size
, align
, maxalign
, c
, offset
;
6617 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
;
6618 Sym
*s
, *ss
, *ass
, **ps
;
6622 a
= tok
; /* save decl type */
6627 /* struct already defined ? return it */
6629 expect("struct/union/enum name");
6633 error("invalid type");
6640 /* we put an undefined size for struct/union */
6641 s
= sym_push(v
| SYM_STRUCT
, &type1
, 0, -1);
6642 s
->r
= 0; /* default alignment is zero as gcc */
6643 /* put struct/union/enum name in type */
6651 error("struct/union/enum already defined");
6652 /* cannot be empty */
6654 /* non empty enums are not allowed */
6655 if (a
== TOK_ENUM
) {
6659 expect("identifier");
6665 /* enum symbols have static storage */
6666 ss
= sym_push(v
, &int_type
, VT_CONST
, c
);
6667 ss
->type
.t
|= VT_STATIC
;
6672 /* NOTE: we accept a trailing comma */
6682 while (tok
!= '}') {
6683 parse_btype(&btype
, &ad
);
6689 type_decl(&type1
, &ad
, &v
, TYPE_DIRECT
| TYPE_ABSTRACT
);
6690 if (v
== 0 && (type1
.t
& VT_BTYPE
) != VT_STRUCT
)
6691 expect("identifier");
6692 if ((type1
.t
& VT_BTYPE
) == VT_FUNC
||
6693 (type1
.t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
| VT_INLINE
)))
6694 error("invalid type for '%s'",
6695 get_tok_str(v
, NULL
));
6699 bit_size
= expr_const();
6700 /* XXX: handle v = 0 case for messages */
6702 error("negative width in bit-field '%s'",
6703 get_tok_str(v
, NULL
));
6704 if (v
&& bit_size
== 0)
6705 error("zero width for bit-field '%s'",
6706 get_tok_str(v
, NULL
));
6708 size
= type_size(&type1
, &align
);
6710 if (align
< ad
.aligned
)
6712 } else if (ad
.packed
) {
6714 } else if (*tcc_state
->pack_stack_ptr
) {
6715 if (align
> *tcc_state
->pack_stack_ptr
)
6716 align
= *tcc_state
->pack_stack_ptr
;
6719 if (bit_size
>= 0) {
6720 bt
= type1
.t
& VT_BTYPE
;
6726 error("bitfields must have scalar type");
6728 if (bit_size
> bsize
) {
6729 error("width of '%s' exceeds its type",
6730 get_tok_str(v
, NULL
));
6731 } else if (bit_size
== bsize
) {
6732 /* no need for bit fields */
6734 } else if (bit_size
== 0) {
6735 /* XXX: what to do if only padding in a
6737 /* zero size: means to pad */
6741 /* we do not have enough room ? */
6742 if ((bit_pos
+ bit_size
) > bsize
)
6745 /* XXX: handle LSB first */
6746 type1
.t
|= VT_BITFIELD
|
6747 (bit_pos
<< VT_STRUCT_SHIFT
) |
6748 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
6749 bit_pos
+= bit_size
;
6754 if (v
!= 0 || (type1
.t
& VT_BTYPE
) == VT_STRUCT
) {
6755 /* add new memory data only if starting
6757 if (lbit_pos
== 0) {
6758 if (a
== TOK_STRUCT
) {
6759 c
= (c
+ align
- 1) & -align
;
6768 if (align
> maxalign
)
6772 printf("add field %s offset=%d",
6773 get_tok_str(v
, NULL
), offset
);
6774 if (type1
.t
& VT_BITFIELD
) {
6775 printf(" pos=%d size=%d",
6776 (type1
.t
>> VT_STRUCT_SHIFT
) & 0x3f,
6777 (type1
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
6782 if (v
== 0 && (type1
.t
& VT_BTYPE
) == VT_STRUCT
) {
6784 while ((ass
= ass
->next
) != NULL
) {
6785 ss
= sym_push(ass
->v
, &ass
->type
, 0, offset
+ ass
->c
);
6790 ss
= sym_push(v
| SYM_FIELD
, &type1
, 0, offset
);
6794 if (tok
== ';' || tok
== TOK_EOF
)
6801 /* store size and alignment */
6802 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
6808 /* return 0 if no type declaration. otherwise, return the basic type
6811 static int parse_btype(CType
*type
, AttributeDef
*ad
)
6813 int t
, u
, type_found
, typespec_found
, typedef_found
;
6817 memset(ad
, 0, sizeof(AttributeDef
));
6825 /* currently, we really ignore extension */
6835 if ((t
& VT_BTYPE
) != 0)
6836 error("too many basic types");
6852 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
6853 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6854 } else if ((t
& VT_BTYPE
) == VT_LONG
) {
6855 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
6869 if ((t
& VT_BTYPE
) == VT_LONG
) {
6870 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6877 struct_decl(&type1
, VT_ENUM
);
6880 type
->ref
= type1
.ref
;
6884 struct_decl(&type1
, VT_STRUCT
);
6887 /* type modifiers */
6940 /* GNUC attribute */
6941 case TOK_ATTRIBUTE1
:
6942 case TOK_ATTRIBUTE2
:
6943 parse_attribute(ad
);
6950 parse_expr_type(&type1
);
6953 if (typespec_found
|| typedef_found
)
6956 if (!s
|| !(s
->type
.t
& VT_TYPEDEF
))
6959 t
|= (s
->type
.t
& ~VT_TYPEDEF
);
6960 type
->ref
= s
->type
.ref
;
6968 if ((t
& (VT_SIGNED
|VT_UNSIGNED
)) == (VT_SIGNED
|VT_UNSIGNED
))
6969 error("signed and unsigned modifier");
6970 if (tcc_state
->char_is_unsigned
) {
6971 if ((t
& (VT_SIGNED
|VT_UNSIGNED
|VT_BTYPE
)) == VT_BYTE
)
6976 /* long is never used as type */
6977 if ((t
& VT_BTYPE
) == VT_LONG
)
6978 t
= (t
& ~VT_BTYPE
) | VT_INT
;
6983 /* convert a function parameter type (array to pointer and function to
6984 function pointer) */
6985 static inline void convert_parameter_type(CType
*pt
)
6987 /* remove const and volatile qualifiers (XXX: const could be used
6988 to indicate a const function parameter */
6989 pt
->t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6990 /* array must be transformed to pointer according to ANSI C */
6992 if ((pt
->t
& VT_BTYPE
) == VT_FUNC
) {
6997 static void post_type(CType
*type
, AttributeDef
*ad
)
7000 Sym
**plast
, *s
, *first
;
7005 /* function declaration */
7012 /* read param name and compute offset */
7013 if (l
!= FUNC_OLD
) {
7014 if (!parse_btype(&pt
, &ad1
)) {
7016 error("invalid type");
7023 if ((pt
.t
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
7025 type_decl(&pt
, &ad1
, &n
, TYPE_DIRECT
| TYPE_ABSTRACT
);
7026 if ((pt
.t
& VT_BTYPE
) == VT_VOID
)
7027 error("parameter declared as void");
7032 expect("identifier");
7036 convert_parameter_type(&pt
);
7037 s
= sym_push(n
| SYM_FIELD
, &pt
, 0, 0);
7043 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
7050 /* if no parameters, then old type prototype */
7054 t1
= type
->t
& VT_STORAGE
;
7055 /* NOTE: const is ignored in returned type as it has a special
7056 meaning in gcc / C++ */
7057 type
->t
&= ~(VT_STORAGE
| VT_CONSTANT
);
7058 post_type(type
, ad
);
7059 /* we push a anonymous symbol which will contain the function prototype */
7060 s
= sym_push(SYM_FIELD
, type
, ad
->func_call
, l
);
7062 type
->t
= t1
| VT_FUNC
;
7064 } else if (tok
== '[') {
7065 /* array definition */
7071 error("invalid array size");
7074 /* parse next post type */
7075 t1
= type
->t
& VT_STORAGE
;
7076 type
->t
&= ~VT_STORAGE
;
7077 post_type(type
, ad
);
7079 /* we push a anonymous symbol which will contain the array
7081 s
= sym_push(SYM_FIELD
, type
, 0, n
);
7082 type
->t
= t1
| VT_ARRAY
| VT_PTR
;
7087 /* Parse a type declaration (except basic type), and return the type
7088 in 'type'. 'td' is a bitmask indicating which kind of type decl is
7089 expected. 'type' should contain the basic type. 'ad' is the
7090 attribute definition of the basic type. It can be modified by
7093 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
)
7096 CType type1
, *type2
;
7099 while (tok
== '*') {
7107 qualifiers
|= VT_CONSTANT
;
7112 qualifiers
|= VT_VOLATILE
;
7120 type
->t
|= qualifiers
;
7123 /* XXX: clarify attribute handling */
7124 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7125 parse_attribute(ad
);
7127 /* recursive type */
7128 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7129 type1
.t
= 0; /* XXX: same as int */
7132 /* XXX: this is not correct to modify 'ad' at this point, but
7133 the syntax is not clear */
7134 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7135 parse_attribute(ad
);
7136 type_decl(&type1
, ad
, v
, td
);
7139 /* type identifier */
7140 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
7144 if (!(td
& TYPE_ABSTRACT
))
7145 expect("identifier");
7149 post_type(type
, ad
);
7150 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7151 parse_attribute(ad
);
7154 /* append type at the end of type1 */
7167 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7168 static int lvalue_type(int t
)
7173 if (bt
== VT_BYTE
|| bt
== VT_BOOL
)
7175 else if (bt
== VT_SHORT
)
7179 if (t
& VT_UNSIGNED
)
7180 r
|= VT_LVAL_UNSIGNED
;
7184 /* indirection with full error checking and bound check */
7185 static void indir(void)
7187 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
) {
7188 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FUNC
)
7192 if ((vtop
->r
& VT_LVAL
) && !nocode_wanted
)
7194 vtop
->type
= *pointed_type(&vtop
->type
);
7195 /* Arrays and functions are never lvalues */
7196 if (!(vtop
->type
.t
& VT_ARRAY
)
7197 && (vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
) {
7198 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7199 /* if bound checking, the referenced pointer must be checked */
7200 if (do_bounds_check
)
7201 vtop
->r
|= VT_MUSTBOUND
;
7205 /* pass a parameter to a function and do type checking and casting */
7206 static void gfunc_param_typed(Sym
*func
, Sym
*arg
)
7211 func_type
= func
->c
;
7212 if (func_type
== FUNC_OLD
||
7213 (func_type
== FUNC_ELLIPSIS
&& arg
== NULL
)) {
7214 /* default casting : only need to convert float to double */
7215 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FLOAT
) {
7219 } else if (arg
== NULL
) {
7220 error("too many arguments to function");
7223 type
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
7224 gen_assign_cast(&type
);
7228 /* parse an expression of the form '(type)' or '(expr)' and return its
7230 static void parse_expr_type(CType
*type
)
7236 if (parse_btype(type
, &ad
)) {
7237 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7244 static void parse_type(CType
*type
)
7249 if (!parse_btype(type
, &ad
)) {
7252 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7255 static void vpush_tokc(int t
)
7259 vsetc(&type
, VT_CONST
, &tokc
);
7262 static void unary(void)
7264 int n
, t
, align
, size
, r
;
7269 /* XXX: GCC 2.95.3 does not generate a table although it should be
7283 vpush_tokc(VT_INT
| VT_UNSIGNED
);
7287 vpush_tokc(VT_LLONG
);
7291 vpush_tokc(VT_LLONG
| VT_UNSIGNED
);
7295 vpush_tokc(VT_FLOAT
);
7299 vpush_tokc(VT_DOUBLE
);
7303 vpush_tokc(VT_LDOUBLE
);
7306 case TOK___FUNCTION__
:
7308 goto tok_identifier
;
7314 /* special function name identifier */
7315 len
= strlen(funcname
) + 1;
7316 /* generate char[len] type */
7321 vpush_ref(&type
, data_section
, data_section
->data_offset
, len
);
7322 ptr
= section_ptr_add(data_section
, len
);
7323 memcpy(ptr
, funcname
, len
);
7328 #ifdef TCC_TARGET_PE
7329 t
= VT_SHORT
| VT_UNSIGNED
;
7335 /* string parsing */
7338 if (tcc_state
->warn_write_strings
)
7343 memset(&ad
, 0, sizeof(AttributeDef
));
7344 decl_initializer_alloc(&type
, &ad
, VT_CONST
, 2, 0, 0);
7349 if (parse_btype(&type
, &ad
)) {
7350 type_decl(&type
, &ad
, &n
, TYPE_ABSTRACT
);
7352 /* check ISOC99 compound literal */
7354 /* data is allocated locally by default */
7359 /* all except arrays are lvalues */
7360 if (!(type
.t
& VT_ARRAY
))
7361 r
|= lvalue_type(type
.t
);
7362 memset(&ad
, 0, sizeof(AttributeDef
));
7363 decl_initializer_alloc(&type
, &ad
, r
, 1, 0, 0);
7368 } else if (tok
== '{') {
7369 /* save all registers */
7371 /* statement expression : we do not accept break/continue
7372 inside as GCC does */
7373 block(NULL
, NULL
, NULL
, NULL
, 0, 1);
7388 /* functions names must be treated as function pointers,
7389 except for unary '&' and sizeof. Since we consider that
7390 functions are not lvalues, we only have to handle it
7391 there and in function calls. */
7392 /* arrays can also be used although they are not lvalues */
7393 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
&&
7394 !(vtop
->type
.t
& VT_ARRAY
) && !(vtop
->type
.t
& VT_LLOCAL
))
7396 mk_pointer(&vtop
->type
);
7402 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
)
7403 vtop
->c
.i
= !vtop
->c
.i
;
7404 else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
7405 vtop
->c
.i
= vtop
->c
.i
^ 1;
7408 vseti(VT_JMP
, gtst(1, 0));
7419 /* in order to force cast, we add zero */
7421 if ((vtop
->type
.t
& VT_BTYPE
) == VT_PTR
)
7422 error("pointer not accepted for unary plus");
7432 parse_expr_type(&type
);
7436 size
= type_size(&type
, &align
);
7437 if (t
== TOK_SIZEOF
) {
7439 error("sizeof applied to an incomplete type");
7444 vtop
->type
.t
|= VT_UNSIGNED
;
7447 case TOK_builtin_types_compatible_p
:
7456 type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7457 type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7458 vpushi(is_compatible_types(&type1
, &type2
));
7461 case TOK_builtin_constant_p
:
7463 int saved_nocode_wanted
, res
;
7466 saved_nocode_wanted
= nocode_wanted
;
7469 res
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
7471 nocode_wanted
= saved_nocode_wanted
;
7491 goto tok_identifier
;
7493 /* allow to take the address of a label */
7494 if (tok
< TOK_UIDENT
)
7495 expect("label identifier");
7496 s
= label_find(tok
);
7498 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
7500 if (s
->r
== LABEL_DECLARED
)
7501 s
->r
= LABEL_FORWARD
;
7504 s
->type
.t
= VT_VOID
;
7505 mk_pointer(&s
->type
);
7506 s
->type
.t
|= VT_STATIC
;
7508 vset(&s
->type
, VT_CONST
| VT_SYM
, 0);
7517 expect("identifier");
7521 error("'%s' undeclared", get_tok_str(t
, NULL
));
7522 /* for simple function calls, we tolerate undeclared
7523 external reference to int() function */
7524 if (tcc_state
->warn_implicit_function_declaration
)
7525 warning("implicit declaration of function '%s'",
7526 get_tok_str(t
, NULL
));
7527 s
= external_global_sym(t
, &func_old_type
, 0);
7529 if ((s
->type
.t
& (VT_STATIC
| VT_INLINE
| VT_BTYPE
)) ==
7530 (VT_STATIC
| VT_INLINE
| VT_FUNC
)) {
7531 /* if referencing an inline function, then we generate a
7532 symbol to it if not already done. It will have the
7533 effect to generate code for it at the end of the
7534 compilation unit. Inline function as always
7535 generated in the text section. */
7537 put_extern_sym(s
, text_section
, 0, 0);
7538 r
= VT_SYM
| VT_CONST
;
7542 vset(&s
->type
, r
, s
->c
);
7543 /* if forward reference, we must point to s */
7544 if (vtop
->r
& VT_SYM
) {
7551 /* post operations */
7553 if (tok
== TOK_INC
|| tok
== TOK_DEC
) {
7556 } else if (tok
== '.' || tok
== TOK_ARROW
) {
7558 if (tok
== TOK_ARROW
)
7563 /* expect pointer on structure */
7564 if ((vtop
->type
.t
& VT_BTYPE
) != VT_STRUCT
)
7565 expect("struct or union");
7569 while ((s
= s
->next
) != NULL
) {
7574 error("field not found");
7575 /* add field offset to pointer */
7576 vtop
->type
= char_pointer_type
; /* change type to 'char *' */
7579 /* change type to field type, and set to lvalue */
7580 vtop
->type
= s
->type
;
7581 /* an array is never an lvalue */
7582 if (!(vtop
->type
.t
& VT_ARRAY
)) {
7583 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7584 /* if bound checking, the referenced pointer must be checked */
7585 if (do_bounds_check
)
7586 vtop
->r
|= VT_MUSTBOUND
;
7589 } else if (tok
== '[') {
7595 } else if (tok
== '(') {
7601 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
) {
7602 /* pointer test (no array accepted) */
7603 if ((vtop
->type
.t
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
7604 vtop
->type
= *pointed_type(&vtop
->type
);
7605 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
)
7609 expect("function pointer");
7612 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
7614 /* get return type */
7617 sa
= s
->next
; /* first parameter */
7619 /* compute first implicit argument if a structure is returned */
7620 if ((s
->type
.t
& VT_BTYPE
) == VT_STRUCT
) {
7621 /* get some space for the returned structure */
7622 size
= type_size(&s
->type
, &align
);
7623 loc
= (loc
- size
) & -align
;
7625 ret
.r
= VT_LOCAL
| VT_LVAL
;
7626 /* pass it as 'int' to avoid structure arg passing
7628 vseti(VT_LOCAL
, loc
);
7634 /* return in register */
7635 if (is_float(ret
.type
.t
)) {
7638 if ((ret
.type
.t
& VT_BTYPE
) == VT_LLONG
)
7647 gfunc_param_typed(s
, sa
);
7657 error("too few arguments to function");
7659 if (!nocode_wanted
) {
7660 gfunc_call(nb_args
);
7662 vtop
-= (nb_args
+ 1);
7665 vsetc(&ret
.type
, ret
.r
, &ret
.c
);
7673 static void uneq(void)
7679 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
7680 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
7681 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
7696 static void expr_prod(void)
7701 while (tok
== '*' || tok
== '/' || tok
== '%') {
7709 static void expr_sum(void)
7714 while (tok
== '+' || tok
== '-') {
7722 static void expr_shift(void)
7727 while (tok
== TOK_SHL
|| tok
== TOK_SAR
) {
7735 static void expr_cmp(void)
7740 while ((tok
>= TOK_ULE
&& tok
<= TOK_GT
) ||
7741 tok
== TOK_ULT
|| tok
== TOK_UGE
) {
7749 static void expr_cmpeq(void)
7754 while (tok
== TOK_EQ
|| tok
== TOK_NE
) {
7762 static void expr_and(void)
7765 while (tok
== '&') {
7772 static void expr_xor(void)
7775 while (tok
== '^') {
7782 static void expr_or(void)
7785 while (tok
== '|') {
7792 /* XXX: fix this mess */
7793 static void expr_land_const(void)
7796 while (tok
== TOK_LAND
) {
7803 /* XXX: fix this mess */
7804 static void expr_lor_const(void)
7807 while (tok
== TOK_LOR
) {
7814 /* only used if non constant */
7815 static void expr_land(void)
7820 if (tok
== TOK_LAND
) {
7825 if (tok
!= TOK_LAND
) {
7835 static void expr_lor(void)
7840 if (tok
== TOK_LOR
) {
7845 if (tok
!= TOK_LOR
) {
7855 /* XXX: better constant handling */
7856 static void expr_eq(void)
7858 int tt
, u
, r1
, r2
, rc
, t1
, t2
, bt1
, bt2
;
7860 CType type
, type1
, type2
;
7869 if (tok
== ':' && gnu_ext
) {
7885 if (vtop
!= vstack
) {
7886 /* needed to avoid having different registers saved in
7888 if (is_float(vtop
->type
.t
))
7895 if (tok
== ':' && gnu_ext
) {
7903 sv
= *vtop
; /* save value to handle it later */
7904 vtop
--; /* no vpop so that FP stack is not flushed */
7912 bt1
= t1
& VT_BTYPE
;
7914 bt2
= t2
& VT_BTYPE
;
7915 /* cast operands to correct type according to ISOC rules */
7916 if (is_float(bt1
) || is_float(bt2
)) {
7917 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
7918 type
.t
= VT_LDOUBLE
;
7919 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
7924 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
7925 /* cast to biggest op */
7927 /* convert to unsigned if it does not fit in a long long */
7928 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
7929 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
7930 type
.t
|= VT_UNSIGNED
;
7931 } else if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
7932 /* XXX: test pointer compatibility */
7934 } else if (bt1
== VT_FUNC
|| bt2
== VT_FUNC
) {
7935 /* XXX: test function pointer compatibility */
7937 } else if (bt1
== VT_STRUCT
|| bt2
== VT_STRUCT
) {
7938 /* XXX: test structure compatibility */
7940 } else if (bt1
== VT_VOID
|| bt2
== VT_VOID
) {
7941 /* NOTE: as an extension, we accept void on only one side */
7944 /* integer operations */
7946 /* convert to unsigned if it does not fit in an integer */
7947 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
7948 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
7949 type
.t
|= VT_UNSIGNED
;
7952 /* now we convert second operand */
7954 if (VT_STRUCT
== (vtop
->type
.t
& VT_BTYPE
))
7957 if (is_float(type
.t
)) {
7959 } else if ((type
.t
& VT_BTYPE
) == VT_LLONG
) {
7960 /* for long longs, we use fixed registers to avoid having
7961 to handle a complicated move */
7966 /* this is horrible, but we must also convert first
7970 /* put again first value and cast it */
7973 if (VT_STRUCT
== (vtop
->type
.t
& VT_BTYPE
))
7983 static void gexpr(void)
7994 /* parse an expression and return its type without any side effect. */
7995 static void expr_type(CType
*type
)
7997 int saved_nocode_wanted
;
7999 saved_nocode_wanted
= nocode_wanted
;
8004 nocode_wanted
= saved_nocode_wanted
;
8007 /* parse a unary expression and return its type without any side
8009 static void unary_type(CType
*type
)
8021 /* parse a constant expression and return value in vtop. */
8022 static void expr_const1(void)
8031 /* parse an integer constant and return its value. */
8032 static int expr_const(void)
8036 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
8037 expect("constant expression");
8043 /* return the label token if current token is a label, otherwise
8045 static int is_label(void)
8049 /* fast test first */
8050 if (tok
< TOK_UIDENT
)
8052 /* no need to save tokc because tok is an identifier */
8059 unget_tok(last_tok
);
8064 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
8065 int case_reg
, int is_expr
)
8070 /* generate line number info */
8072 (last_line_num
!= file
->line_num
|| last_ind
!= ind
)) {
8073 put_stabn(N_SLINE
, 0, file
->line_num
, ind
- func_ind
);
8075 last_line_num
= file
->line_num
;
8079 /* default return value is (void) */
8081 vtop
->type
.t
= VT_VOID
;
8084 if (tok
== TOK_IF
) {
8091 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
8093 if (c
== TOK_ELSE
) {
8097 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
8098 gsym(d
); /* patch else jmp */
8101 } else if (tok
== TOK_WHILE
) {
8109 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8113 } else if (tok
== '{') {
8117 /* record local declaration stack position */
8119 llabel
= local_label_stack
;
8120 /* handle local labels declarations */
8121 if (tok
== TOK_LABEL
) {
8124 if (tok
< TOK_UIDENT
)
8125 expect("label identifier");
8126 label_push(&local_label_stack
, tok
, LABEL_DECLARED
);
8136 while (tok
!= '}') {
8141 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
8144 /* pop locally defined labels */
8145 label_pop(&local_label_stack
, llabel
);
8146 /* pop locally defined symbols */
8147 sym_pop(&local_stack
, s
);
8149 } else if (tok
== TOK_RETURN
) {
8153 gen_assign_cast(&func_vt
);
8154 if ((func_vt
.t
& VT_BTYPE
) == VT_STRUCT
) {
8156 /* if returning structure, must copy it to implicit
8157 first pointer arg location */
8160 size
= type_size(&func_vt
,&align
);
8163 if((vtop
->r
!= (VT_LOCAL
| VT_LVAL
) || (vtop
->c
.i
& 3))
8167 loc
= (loc
- size
) & -4;
8170 vset(&type
, VT_LOCAL
| VT_LVAL
, addr
);
8173 vset(&int_type
, VT_LOCAL
| VT_LVAL
, addr
);
8175 vtop
->type
= int_type
;
8181 vset(&type
, VT_LOCAL
| VT_LVAL
, func_vc
);
8184 /* copy structure value to pointer */
8189 } else if (is_float(func_vt
.t
)) {
8194 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
8197 rsym
= gjmp(rsym
); /* jmp */
8198 } else if (tok
== TOK_BREAK
) {
8201 error("cannot break");
8202 *bsym
= gjmp(*bsym
);
8205 } else if (tok
== TOK_CONTINUE
) {
8208 error("cannot continue");
8209 *csym
= gjmp(*csym
);
8212 } else if (tok
== TOK_FOR
) {
8239 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8244 if (tok
== TOK_DO
) {
8249 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8260 if (tok
== TOK_SWITCH
) {
8264 /* XXX: other types than integer */
8265 case_reg
= gv(RC_INT
);
8269 b
= gjmp(0); /* jump to first case */
8271 block(&a
, csym
, &b
, &c
, case_reg
, 0);
8272 /* if no default, jmp after switch */
8280 if (tok
== TOK_CASE
) {
8287 if (gnu_ext
&& tok
== TOK_DOTS
) {
8291 warning("empty case range");
8293 /* since a case is like a label, we must skip it with a jmp */
8300 *case_sym
= gtst(1, 0);
8303 *case_sym
= gtst(1, 0);
8307 *case_sym
= gtst(1, *case_sym
);
8312 goto block_after_label
;
8314 if (tok
== TOK_DEFAULT
) {
8320 error("too many 'default'");
8323 goto block_after_label
;
8325 if (tok
== TOK_GOTO
) {
8327 if (tok
== '*' && gnu_ext
) {
8331 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
8334 } else if (tok
>= TOK_UIDENT
) {
8335 s
= label_find(tok
);
8336 /* put forward definition if needed */
8338 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
8340 if (s
->r
== LABEL_DECLARED
)
8341 s
->r
= LABEL_FORWARD
;
8343 /* label already defined */
8344 if (s
->r
& LABEL_FORWARD
)
8345 s
->next
= (void *)gjmp((long)s
->next
);
8347 gjmp_addr((long)s
->next
);
8350 expect("label identifier");
8353 } else if (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
) {
8361 if (s
->r
== LABEL_DEFINED
)
8362 error("duplicate label '%s'", get_tok_str(s
->v
, NULL
));
8363 gsym((long)s
->next
);
8364 s
->r
= LABEL_DEFINED
;
8366 s
= label_push(&global_label_stack
, b
, LABEL_DEFINED
);
8368 s
->next
= (void *)ind
;
8369 /* we accept this, but it is a mistake */
8372 warning("deprecated use of label at end of compound statement");
8376 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
8379 /* expression case */
8394 /* t is the array or struct type. c is the array or struct
8395 address. cur_index/cur_field is the pointer to the current
8396 value. 'size_only' is true if only size info is needed (only used
8398 static void decl_designator(CType
*type
, Section
*sec
, unsigned long c
,
8399 int *cur_index
, Sym
**cur_field
,
8403 int notfirst
, index
, index_last
, align
, l
, nb_elems
, elem_size
;
8409 if (gnu_ext
&& (l
= is_label()) != 0)
8411 while (tok
== '[' || tok
== '.') {
8413 if (!(type
->t
& VT_ARRAY
))
8414 expect("array type");
8417 index
= expr_const();
8418 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
8419 expect("invalid index");
8420 if (tok
== TOK_DOTS
&& gnu_ext
) {
8422 index_last
= expr_const();
8423 if (index_last
< 0 ||
8424 (s
->c
>= 0 && index_last
>= s
->c
) ||
8426 expect("invalid index");
8432 *cur_index
= index_last
;
8433 type
= pointed_type(type
);
8434 elem_size
= type_size(type
, &align
);
8435 c
+= index
* elem_size
;
8436 /* NOTE: we only support ranges for last designator */
8437 nb_elems
= index_last
- index
+ 1;
8438 if (nb_elems
!= 1) {
8447 if ((type
->t
& VT_BTYPE
) != VT_STRUCT
)
8448 expect("struct/union type");
8461 /* XXX: fix this mess by using explicit storage field */
8463 type1
.t
|= (type
->t
& ~VT_TYPE
);
8477 if (type
->t
& VT_ARRAY
) {
8479 type
= pointed_type(type
);
8480 c
+= index
* type_size(type
, &align
);
8484 error("too many field init");
8485 /* XXX: fix this mess by using explicit storage field */
8487 type1
.t
|= (type
->t
& ~VT_TYPE
);
8492 decl_initializer(type
, sec
, c
, 0, size_only
);
8494 /* XXX: make it more general */
8495 if (!size_only
&& nb_elems
> 1) {
8496 unsigned long c_end
;
8501 error("range init not supported yet for dynamic storage");
8502 c_end
= c
+ nb_elems
* elem_size
;
8503 if (c_end
> sec
->data_allocated
)
8504 section_realloc(sec
, c_end
);
8505 src
= sec
->data
+ c
;
8507 for(i
= 1; i
< nb_elems
; i
++) {
8509 memcpy(dst
, src
, elem_size
);
8515 #define EXPR_CONST 1
8518 /* store a value or an expression directly in global data or in local array */
8519 static void init_putv(CType
*type
, Section
*sec
, unsigned long c
,
8520 int v
, int expr_type
)
8522 int saved_global_expr
, bt
, bit_pos
, bit_size
;
8524 unsigned long long bit_mask
;
8532 /* compound literals must be allocated globally in this case */
8533 saved_global_expr
= global_expr
;
8536 global_expr
= saved_global_expr
;
8537 /* NOTE: symbols are accepted */
8538 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) != VT_CONST
)
8539 error("initializer element is not constant");
8547 dtype
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
8550 /* XXX: not portable */
8551 /* XXX: generate error if incorrect relocation */
8552 gen_assign_cast(&dtype
);
8553 bt
= type
->t
& VT_BTYPE
;
8554 ptr
= sec
->data
+ c
;
8555 /* XXX: make code faster ? */
8556 if (!(type
->t
& VT_BITFIELD
)) {
8561 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
8562 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
8563 bit_mask
= (1LL << bit_size
) - 1;
8565 if ((vtop
->r
& VT_SYM
) &&
8571 (bt
== VT_INT
&& bit_size
!= 32)))
8572 error("initializer element is not computable at load time");
8575 *(char *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8578 *(short *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8581 *(double *)ptr
= vtop
->c
.d
;
8584 *(long double *)ptr
= vtop
->c
.ld
;
8587 *(long long *)ptr
|= (vtop
->c
.ll
& bit_mask
) << bit_pos
;
8590 if (vtop
->r
& VT_SYM
) {
8591 greloc(sec
, vtop
->sym
, c
, R_DATA_32
);
8593 *(int *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8598 vset(&dtype
, VT_LOCAL
|VT_LVAL
, c
);
8605 /* put zeros for variable based init */
8606 static void init_putz(CType
*t
, Section
*sec
, unsigned long c
, int size
)
8609 /* nothing to do because globals are already set to zero */
8611 vpush_global_sym(&func_old_type
, TOK_memset
);
8619 /* 't' contains the type and storage info. 'c' is the offset of the
8620 object in section 'sec'. If 'sec' is NULL, it means stack based
8621 allocation. 'first' is true if array '{' must be read (multi
8622 dimension implicit array init handling). 'size_only' is true if
8623 size only evaluation is wanted (only for arrays). */
8624 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
8625 int first
, int size_only
)
8627 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
8628 int size1
, align1
, expr_type
;
8632 if (type
->t
& VT_ARRAY
) {
8636 t1
= pointed_type(type
);
8637 size1
= type_size(t1
, &align1
);
8640 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
8646 /* only parse strings here if correct type (otherwise: handle
8647 them as ((w)char *) expressions */
8648 if ((tok
== TOK_LSTR
&&
8649 #ifdef TCC_TARGET_PE
8650 (t1
->t
& VT_BTYPE
) == VT_SHORT
&& (t1
->t
& VT_UNSIGNED
)) ||
8652 (t1
->t
& VT_BTYPE
) == VT_INT
) ||
8655 (t1
->t
& VT_BTYPE
) == VT_BYTE
)) {
8656 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8661 /* compute maximum number of chars wanted */
8663 cstr_len
= cstr
->size
;
8665 cstr_len
= cstr
->size
/ sizeof(nwchar_t
);
8668 if (n
>= 0 && nb
> (n
- array_length
))
8669 nb
= n
- array_length
;
8672 warning("initializer-string for array is too long");
8673 /* in order to go faster for common case (char
8674 string in global variable, we handle it
8676 if (sec
&& tok
== TOK_STR
&& size1
== 1) {
8677 memcpy(sec
->data
+ c
+ array_length
, cstr
->data
, nb
);
8681 ch
= ((unsigned char *)cstr
->data
)[i
];
8683 ch
= ((nwchar_t
*)cstr
->data
)[i
];
8684 init_putv(t1
, sec
, c
+ (array_length
+ i
) * size1
,
8692 /* only add trailing zero if enough storage (no
8693 warning in this case since it is standard) */
8694 if (n
< 0 || array_length
< n
) {
8696 init_putv(t1
, sec
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
8702 while (tok
!= '}') {
8703 decl_designator(type
, sec
, c
, &index
, NULL
, size_only
);
8704 if (n
>= 0 && index
>= n
)
8705 error("index too large");
8706 /* must put zero in holes (note that doing it that way
8707 ensures that it even works with designators) */
8708 if (!size_only
&& array_length
< index
) {
8709 init_putz(t1
, sec
, c
+ array_length
* size1
,
8710 (index
- array_length
) * size1
);
8713 if (index
> array_length
)
8714 array_length
= index
;
8715 /* special test for multi dimensional arrays (may not
8716 be strictly correct if designators are used at the
8718 if (index
>= n
&& no_oblock
)
8727 /* put zeros at the end */
8728 if (!size_only
&& n
>= 0 && array_length
< n
) {
8729 init_putz(t1
, sec
, c
+ array_length
* size1
,
8730 (n
- array_length
) * size1
);
8732 /* patch type size if needed */
8734 s
->c
= array_length
;
8735 } else if ((type
->t
& VT_BTYPE
) == VT_STRUCT
&&
8736 (sec
|| !first
|| tok
== '{')) {
8739 /* NOTE: the previous test is a specific case for automatic
8740 struct/union init */
8741 /* XXX: union needs only one init */
8743 /* XXX: this test is incorrect for local initializers
8744 beginning with ( without {. It would be much more difficult
8745 to do it correctly (ideally, the expression parser should
8746 be used in all cases) */
8752 while (tok
== '(') {
8756 if (!parse_btype(&type1
, &ad1
))
8758 type_decl(&type1
, &ad1
, &n
, TYPE_ABSTRACT
);
8760 if (!is_assignable_types(type
, &type1
))
8761 error("invalid type for cast");
8766 if (first
|| tok
== '{') {
8775 while (tok
!= '}') {
8776 decl_designator(type
, sec
, c
, NULL
, &f
, size_only
);
8778 if (!size_only
&& array_length
< index
) {
8779 init_putz(type
, sec
, c
+ array_length
,
8780 index
- array_length
);
8782 index
= index
+ type_size(&f
->type
, &align1
);
8783 if (index
> array_length
)
8784 array_length
= index
;
8786 if (no_oblock
&& f
== NULL
)
8792 /* put zeros at the end */
8793 if (!size_only
&& array_length
< n
) {
8794 init_putz(type
, sec
, c
+ array_length
,
8803 } else if (tok
== '{') {
8805 decl_initializer(type
, sec
, c
, first
, size_only
);
8807 } else if (size_only
) {
8808 /* just skip expression */
8810 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
8814 else if (tok
== ')')
8819 /* currently, we always use constant expression for globals
8820 (may change for scripting case) */
8821 expr_type
= EXPR_CONST
;
8823 expr_type
= EXPR_ANY
;
8824 init_putv(type
, sec
, c
, 0, expr_type
);
8828 /* parse an initializer for type 't' if 'has_init' is non zero, and
8829 allocate space in local or global data space ('r' is either
8830 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8831 variable 'v' of scope 'scope' is declared before initializers are
8832 parsed. If 'v' is zero, then a reference to the new object is put
8833 in the value stack. If 'has_init' is 2, a special parsing is done
8834 to handle string constants. */
8835 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
8836 int has_init
, int v
, int scope
)
8838 int size
, align
, addr
, data_offset
;
8840 ParseState saved_parse_state
;
8841 TokenString init_str
;
8844 size
= type_size(type
, &align
);
8845 /* If unknown size, we must evaluate it before
8846 evaluating initializers because
8847 initializers can generate global data too
8848 (e.g. string pointers or ISOC99 compound
8849 literals). It also simplifies local
8850 initializers handling */
8851 tok_str_new(&init_str
);
8854 error("unknown type size");
8855 /* get all init string */
8856 if (has_init
== 2) {
8857 /* only get strings */
8858 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8859 tok_str_add_tok(&init_str
);
8864 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
8866 error("unexpected end of file in initializer");
8867 tok_str_add_tok(&init_str
);
8870 else if (tok
== '}') {
8878 tok_str_add(&init_str
, -1);
8879 tok_str_add(&init_str
, 0);
8882 save_parse_state(&saved_parse_state
);
8884 macro_ptr
= init_str
.str
;
8886 decl_initializer(type
, NULL
, 0, 1, 1);
8887 /* prepare second initializer parsing */
8888 macro_ptr
= init_str
.str
;
8891 /* if still unknown size, error */
8892 size
= type_size(type
, &align
);
8894 error("unknown type size");
8896 /* take into account specified alignment if bigger */
8898 if (ad
->aligned
> align
)
8899 align
= ad
->aligned
;
8900 } else if (ad
->packed
) {
8903 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
8905 if (do_bounds_check
&& (type
->t
& VT_ARRAY
))
8907 loc
= (loc
- size
) & -align
;
8909 /* handles bounds */
8910 /* XXX: currently, since we do only one pass, we cannot track
8911 '&' operators, so we add only arrays */
8912 if (do_bounds_check
&& (type
->t
& VT_ARRAY
)) {
8913 unsigned long *bounds_ptr
;
8914 /* add padding between regions */
8916 /* then add local bound info */
8917 bounds_ptr
= section_ptr_add(lbounds_section
, 2 * sizeof(unsigned long));
8918 bounds_ptr
[0] = addr
;
8919 bounds_ptr
[1] = size
;
8922 /* local variable */
8923 sym_push(v
, type
, r
, addr
);
8925 /* push local reference */
8926 vset(type
, r
, addr
);
8932 if (v
&& scope
== VT_CONST
) {
8933 /* see if the symbol was already defined */
8936 if (!is_compatible_types(&sym
->type
, type
))
8937 error("incompatible types for redefinition of '%s'",
8938 get_tok_str(v
, NULL
));
8939 if (sym
->type
.t
& VT_EXTERN
) {
8940 /* if the variable is extern, it was not allocated */
8941 sym
->type
.t
&= ~VT_EXTERN
;
8942 /* set array size if it was ommited in extern
8944 if ((sym
->type
.t
& VT_ARRAY
) &&
8945 sym
->type
.ref
->c
< 0 &&
8947 sym
->type
.ref
->c
= type
->ref
->c
;
8949 /* we accept several definitions of the same
8950 global variable. this is tricky, because we
8951 must play with the SHN_COMMON type of the symbol */
8952 /* XXX: should check if the variable was already
8953 initialized. It is incorrect to initialized it
8955 /* no init data, we won't add more to the symbol */
8962 /* allocate symbol in corresponding section */
8967 else if (tcc_state
->nocommon
)
8971 data_offset
= sec
->data_offset
;
8972 data_offset
= (data_offset
+ align
- 1) & -align
;
8974 /* very important to increment global pointer at this time
8975 because initializers themselves can create new initializers */
8976 data_offset
+= size
;
8977 /* add padding if bound check */
8978 if (do_bounds_check
)
8980 sec
->data_offset
= data_offset
;
8981 /* allocate section space to put the data */
8982 if (sec
->sh_type
!= SHT_NOBITS
&&
8983 data_offset
> sec
->data_allocated
)
8984 section_realloc(sec
, data_offset
);
8985 /* align section if needed */
8986 if (align
> sec
->sh_addralign
)
8987 sec
->sh_addralign
= align
;
8989 addr
= 0; /* avoid warning */
8993 if (scope
!= VT_CONST
|| !sym
) {
8994 sym
= sym_push(v
, type
, r
| VT_SYM
, 0);
8996 /* update symbol definition */
8998 put_extern_sym(sym
, sec
, addr
, size
);
9001 /* put a common area */
9002 put_extern_sym(sym
, NULL
, align
, size
);
9003 /* XXX: find a nicer way */
9004 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
9005 esym
->st_shndx
= SHN_COMMON
;
9010 /* push global reference */
9011 sym
= get_sym_ref(type
, sec
, addr
, size
);
9013 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
9017 /* handles bounds now because the symbol must be defined
9018 before for the relocation */
9019 if (do_bounds_check
) {
9020 unsigned long *bounds_ptr
;
9022 greloc(bounds_section
, sym
, bounds_section
->data_offset
, R_DATA_32
);
9023 /* then add global bound info */
9024 bounds_ptr
= section_ptr_add(bounds_section
, 2 * sizeof(long));
9025 bounds_ptr
[0] = 0; /* relocated */
9026 bounds_ptr
[1] = size
;
9030 decl_initializer(type
, sec
, addr
, 1, 0);
9031 /* restore parse state if needed */
9033 tok_str_free(init_str
.str
);
9034 restore_parse_state(&saved_parse_state
);
9040 void put_func_debug(Sym
*sym
)
9045 /* XXX: we put here a dummy type */
9046 snprintf(buf
, sizeof(buf
), "%s:%c1",
9047 funcname
, sym
->type
.t
& VT_STATIC
? 'f' : 'F');
9048 put_stabs_r(buf
, N_FUN
, 0, file
->line_num
, 0,
9049 cur_text_section
, sym
->c
);
9054 /* parse an old style function declaration list */
9055 /* XXX: check multiple parameter */
9056 static void func_decl_list(Sym
*func_sym
)
9063 /* parse each declaration */
9064 while (tok
!= '{' && tok
!= ';' && tok
!= ',' && tok
!= TOK_EOF
) {
9065 if (!parse_btype(&btype
, &ad
))
9066 expect("declaration list");
9067 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
9068 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
9070 /* we accept no variable after */
9074 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
9075 /* find parameter in function parameter list */
9078 if ((s
->v
& ~SYM_FIELD
) == v
)
9082 error("declaration for parameter '%s' but no such parameter",
9083 get_tok_str(v
, NULL
));
9085 /* check that no storage specifier except 'register' was given */
9086 if (type
.t
& VT_STORAGE
)
9087 error("storage class specified for '%s'", get_tok_str(v
, NULL
));
9088 convert_parameter_type(&type
);
9089 /* we can add the type (NOTE: it could be local to the function) */
9091 /* accept other parameters */
9102 /* parse a function defined by symbol 'sym' and generate its code in
9103 'cur_text_section' */
9104 static void gen_function(Sym
*sym
)
9106 int saved_nocode_wanted
= nocode_wanted
;
9108 ind
= cur_text_section
->data_offset
;
9109 /* NOTE: we patch the symbol size later */
9110 put_extern_sym(sym
, cur_text_section
, ind
, 0);
9111 funcname
= get_tok_str(sym
->v
, NULL
);
9113 /* put debug symbol */
9115 put_func_debug(sym
);
9116 /* push a dummy symbol to enable local sym storage */
9117 sym_push2(&local_stack
, SYM_FIELD
, 0, 0);
9118 gfunc_prolog(&sym
->type
);
9120 block(NULL
, NULL
, NULL
, NULL
, 0, 0);
9123 cur_text_section
->data_offset
= ind
;
9124 label_pop(&global_label_stack
, NULL
);
9125 sym_pop(&local_stack
, NULL
); /* reset local stack */
9126 /* end of function */
9127 /* patch symbol size */
9128 ((Elf32_Sym
*)symtab_section
->data
)[sym
->c
].st_size
=
9131 put_stabn(N_FUN
, 0, 0, ind
- func_ind
);
9133 funcname
= ""; /* for safety */
9134 func_vt
.t
= VT_VOID
; /* for safety */
9135 ind
= 0; /* for safety */
9136 nocode_wanted
= saved_nocode_wanted
;
9139 static void gen_inline_functions(void)
9143 int *str
, inline_generated
;
9145 /* iterate while inline function are referenced */
9147 inline_generated
= 0;
9148 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
9150 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
9151 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
9152 (VT_STATIC
| VT_INLINE
) &&
9154 /* the function was used: generate its code and
9155 convert it to a normal function */
9156 str
= (int *)sym
->r
;
9157 sym
->r
= VT_SYM
| VT_CONST
;
9158 type
->t
&= ~VT_INLINE
;
9162 cur_text_section
= text_section
;
9164 macro_ptr
= NULL
; /* fail safe */
9167 inline_generated
= 1;
9170 if (!inline_generated
)
9174 /* free all remaining inline function tokens */
9175 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
9177 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
9178 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
9179 (VT_STATIC
| VT_INLINE
)) {
9180 str
= (int *)sym
->r
;
9182 sym
->r
= 0; /* fail safe */
9187 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9188 static void decl(int l
)
9196 if (!parse_btype(&btype
, &ad
)) {
9197 /* skip redundant ';' */
9198 /* XXX: find more elegant solution */
9203 if (l
== VT_CONST
&&
9204 (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
)) {
9205 /* global asm block */
9209 /* special test for old K&R protos without explicit int
9210 type. Only accepted when defining global data */
9211 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
9215 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
9216 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
9218 /* we accept no variable after */
9222 while (1) { /* iterate thru each declaration */
9224 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
9228 type_to_str(buf
, sizeof(buf
), &type
, get_tok_str(v
, NULL
));
9229 printf("type = '%s'\n", buf
);
9232 if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9233 /* if old style function prototype, we accept a
9236 if (sym
->c
== FUNC_OLD
)
9237 func_decl_list(sym
);
9242 error("cannot use local functions");
9243 if ((type
.t
& VT_BTYPE
) != VT_FUNC
)
9244 expect("function definition");
9246 /* reject abstract declarators in function definition */
9248 while ((sym
= sym
->next
) != NULL
)
9249 if (!(sym
->v
& ~SYM_FIELD
))
9250 expect("identifier");
9252 /* XXX: cannot do better now: convert extern line to static inline */
9253 if ((type
.t
& (VT_EXTERN
| VT_INLINE
)) == (VT_EXTERN
| VT_INLINE
))
9254 type
.t
= (type
.t
& ~VT_EXTERN
) | VT_STATIC
;
9258 if ((sym
->type
.t
& VT_BTYPE
) != VT_FUNC
)
9260 /* specific case: if not func_call defined, we put
9261 the one of the prototype */
9262 /* XXX: should have default value */
9263 if (sym
->type
.ref
->r
!= FUNC_CDECL
&&
9264 type
.ref
->r
== FUNC_CDECL
)
9265 type
.ref
->r
= sym
->type
.ref
->r
;
9266 if (!is_compatible_types(&sym
->type
, &type
)) {
9268 error("incompatible types for redefinition of '%s'",
9269 get_tok_str(v
, NULL
));
9271 /* if symbol is already defined, then put complete type */
9274 /* put function symbol */
9275 sym
= global_identifier_push(v
, type
.t
, 0);
9276 sym
->type
.ref
= type
.ref
;
9279 /* static inline functions are just recorded as a kind
9280 of macro. Their code will be emitted at the end of
9281 the compilation unit only if they are used */
9282 if ((type
.t
& (VT_INLINE
| VT_STATIC
)) ==
9283 (VT_INLINE
| VT_STATIC
)) {
9284 TokenString func_str
;
9287 tok_str_new(&func_str
);
9293 error("unexpected end of file");
9294 tok_str_add_tok(&func_str
);
9299 } else if (t
== '}') {
9301 if (block_level
== 0)
9305 tok_str_add(&func_str
, -1);
9306 tok_str_add(&func_str
, 0);
9307 sym
->r
= (int)func_str
.str
;
9309 /* compute text section */
9310 cur_text_section
= ad
.section
;
9311 if (!cur_text_section
)
9312 cur_text_section
= text_section
;
9313 sym
->r
= VT_SYM
| VT_CONST
;
9315 #ifdef TCC_TARGET_PE
9317 ((Elf32_Sym
*)symtab_section
->data
)[sym
->c
].st_other
|= 1;
9323 if (btype
.t
& VT_TYPEDEF
) {
9324 /* save typedefed type */
9325 /* XXX: test storage specifiers ? */
9326 sym
= sym_push(v
, &type
, 0, 0);
9327 sym
->type
.t
|= VT_TYPEDEF
;
9328 } else if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9329 /* external function definition */
9330 /* specific case for func_call attribute */
9332 type
.ref
->r
= ad
.func_call
;
9333 external_sym(v
, &type
, 0);
9335 /* not lvalue if array */
9337 if (!(type
.t
& VT_ARRAY
))
9338 r
|= lvalue_type(type
.t
);
9339 has_init
= (tok
== '=');
9340 if ((btype
.t
& VT_EXTERN
) ||
9341 ((type
.t
& VT_ARRAY
) && (type
.t
& VT_STATIC
) &&
9342 !has_init
&& l
== VT_CONST
&& type
.ref
->c
< 0)) {
9343 /* external variable */
9344 /* NOTE: as GCC, uninitialized global static
9345 arrays of null size are considered as
9347 external_sym(v
, &type
, r
);
9349 type
.t
|= (btype
.t
& VT_STATIC
); /* Retain "static". */
9350 if (type
.t
& VT_STATIC
)
9356 decl_initializer_alloc(&type
, &ad
, r
,
9370 /* better than nothing, but needs extension to handle '-E' option
9372 static void preprocess_init(TCCState
*s1
)
9374 s1
->include_stack_ptr
= s1
->include_stack
;
9375 /* XXX: move that before to avoid having to initialize
9376 file->ifdef_stack_ptr ? */
9377 s1
->ifdef_stack_ptr
= s1
->ifdef_stack
;
9378 file
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
9380 /* XXX: not ANSI compliant: bound checking says error */
9382 s1
->pack_stack
[0] = 0;
9383 s1
->pack_stack_ptr
= s1
->pack_stack
;
9386 /* compile the C file opened in 'file'. Return non zero if errors. */
9387 static int tcc_compile(TCCState
*s1
)
9391 volatile int section_sym
;
9394 printf("%s: **** new file\n", file
->filename
);
9396 preprocess_init(s1
);
9399 anon_sym
= SYM_FIRST_ANOM
;
9401 /* file info: full path + filename */
9402 section_sym
= 0; /* avoid warning */
9404 section_sym
= put_elf_sym(symtab_section
, 0, 0,
9405 ELF32_ST_INFO(STB_LOCAL
, STT_SECTION
), 0,
9406 text_section
->sh_num
, NULL
);
9407 getcwd(buf
, sizeof(buf
));
9409 normalize_slashes(buf
);
9411 pstrcat(buf
, sizeof(buf
), "/");
9412 put_stabs_r(buf
, N_SO
, 0, 0,
9413 text_section
->data_offset
, text_section
, section_sym
);
9414 put_stabs_r(file
->filename
, N_SO
, 0, 0,
9415 text_section
->data_offset
, text_section
, section_sym
);
9417 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9418 symbols can be safely used */
9419 put_elf_sym(symtab_section
, 0, 0,
9420 ELF32_ST_INFO(STB_LOCAL
, STT_FILE
), 0,
9421 SHN_ABS
, file
->filename
);
9423 /* define some often used types */
9424 int_type
.t
= VT_INT
;
9426 char_pointer_type
.t
= VT_BYTE
;
9427 mk_pointer(&char_pointer_type
);
9429 func_old_type
.t
= VT_FUNC
;
9430 func_old_type
.ref
= sym_push(SYM_FIELD
, &int_type
, FUNC_CDECL
, FUNC_OLD
);
9432 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
9433 float_type
.t
= VT_FLOAT
;
9434 double_type
.t
= VT_DOUBLE
;
9436 func_float_type
.t
= VT_FUNC
;
9437 func_float_type
.ref
= sym_push(SYM_FIELD
, &float_type
, FUNC_CDECL
, FUNC_OLD
);
9438 func_double_type
.t
= VT_FUNC
;
9439 func_double_type
.ref
= sym_push(SYM_FIELD
, &double_type
, FUNC_CDECL
, FUNC_OLD
);
9443 /* define 'void *alloca(unsigned int)' builtin function */
9448 sym
= sym_push(p
, mk_pointer(VT_VOID
), FUNC_CDECL
, FUNC_NEW
);
9449 s1
= sym_push(SYM_FIELD
, VT_UNSIGNED
| VT_INT
, 0, 0);
9452 sym_push(TOK_alloca
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), VT_CONST
, 0);
9456 define_start
= define_stack
;
9459 if (setjmp(s1
->error_jmp_buf
) == 0) {
9461 s1
->error_set_jmp_enabled
= 1;
9463 ch
= file
->buf_ptr
[0];
9464 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
9465 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
;
9469 expect("declaration");
9471 /* end of translation unit info */
9473 put_stabs_r(NULL
, N_SO
, 0, 0,
9474 text_section
->data_offset
, text_section
, section_sym
);
9477 s1
->error_set_jmp_enabled
= 0;
9479 /* reset define stack, but leave -Dsymbols (may be incorrect if
9480 they are undefined) */
9481 free_defines(define_start
);
9483 gen_inline_functions();
9485 sym_pop(&global_stack
, NULL
);
9487 return s1
->nb_errors
!= 0 ? -1 : 0;
9490 /* Preprocess the current file */
9491 /* XXX: add line and file infos, add options to preserve spaces */
9492 static int tcc_preprocess(TCCState
*s1
)
9497 preprocess_init(s1
);
9499 define_start
= define_stack
;
9501 ch
= file
->buf_ptr
[0];
9502 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
9503 parse_flags
= PARSE_FLAG_ASM_COMMENTS
| PARSE_FLAG_PREPROCESS
|
9504 PARSE_FLAG_LINEFEED
;
9508 if (tok
== TOK_EOF
) {
9510 } else if (tok
== TOK_LINEFEED
) {
9514 fputc(' ', s1
->outfile
);
9517 fputs(get_tok_str(tok
, &tokc
), s1
->outfile
);
9520 free_defines(define_start
);
9525 int tcc_compile_string(TCCState
*s
, const char *str
)
9527 BufferedFile bf1
, *bf
= &bf1
;
9531 /* init file structure */
9533 /* XXX: avoid copying */
9535 buf
= tcc_malloc(len
+ 1);
9538 memcpy(buf
, str
, len
);
9541 bf
->buf_end
= buf
+ len
;
9542 pstrcpy(bf
->filename
, sizeof(bf
->filename
), "<string>");
9546 ret
= tcc_compile(s
);
9550 /* currently, no need to close */
9555 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9556 void tcc_define_symbol(TCCState
*s1
, const char *sym
, const char *value
)
9558 BufferedFile bf1
, *bf
= &bf1
;
9560 pstrcpy(bf
->buffer
, IO_BUF_SIZE
, sym
);
9561 pstrcat(bf
->buffer
, IO_BUF_SIZE
, " ");
9565 pstrcat(bf
->buffer
, IO_BUF_SIZE
, value
);
9567 /* init file structure */
9569 bf
->buf_ptr
= bf
->buffer
;
9570 bf
->buf_end
= bf
->buffer
+ strlen(bf
->buffer
);
9571 *bf
->buf_end
= CH_EOB
;
9572 bf
->filename
[0] = '\0';
9576 s1
->include_stack_ptr
= s1
->include_stack
;
9578 /* parse with define parser */
9579 ch
= file
->buf_ptr
[0];
9585 /* undefine a preprocessor symbol */
9586 void tcc_undefine_symbol(TCCState
*s1
, const char *sym
)
9590 ts
= tok_alloc(sym
, strlen(sym
));
9591 s
= define_find(ts
->tok
);
9592 /* undefine symbol by putting an invalid name */
9597 #ifdef CONFIG_TCC_ASM
9599 #ifdef TCC_TARGET_I386
9600 #include "i386-asm.c"
9605 static void asm_instr(void)
9607 error("inline asm() not supported");
9609 static void asm_global_instr(void)
9611 error("inline asm() not supported");
9617 #ifdef TCC_TARGET_COFF
9618 #include "tcccoff.c"
9621 #ifdef TCC_TARGET_PE
9625 /* print the position in the source file of PC value 'pc' by reading
9626 the stabs debug information */
9627 static void rt_printline(unsigned long wanted_pc
)
9629 Stab_Sym
*sym
, *sym_end
;
9630 char func_name
[128], last_func_name
[128];
9631 unsigned long func_addr
, last_pc
, pc
;
9632 const char *incl_files
[INCLUDE_STACK_SIZE
];
9633 int incl_index
, len
, last_line_num
, i
;
9634 const char *str
, *p
;
9636 fprintf(stderr
, "0x%08lx:", wanted_pc
);
9638 func_name
[0] = '\0';
9641 last_func_name
[0] = '\0';
9642 last_pc
= 0xffffffff;
9644 sym
= (Stab_Sym
*)stab_section
->data
+ 1;
9645 sym_end
= (Stab_Sym
*)(stab_section
->data
+ stab_section
->data_offset
);
9646 while (sym
< sym_end
) {
9647 switch(sym
->n_type
) {
9648 /* function start or end */
9650 if (sym
->n_strx
== 0) {
9651 /* we test if between last line and end of function */
9652 pc
= sym
->n_value
+ func_addr
;
9653 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
9655 func_name
[0] = '\0';
9658 str
= stabstr_section
->data
+ sym
->n_strx
;
9659 p
= strchr(str
, ':');
9661 pstrcpy(func_name
, sizeof(func_name
), str
);
9664 if (len
> sizeof(func_name
) - 1)
9665 len
= sizeof(func_name
) - 1;
9666 memcpy(func_name
, str
, len
);
9667 func_name
[len
] = '\0';
9669 func_addr
= sym
->n_value
;
9672 /* line number info */
9674 pc
= sym
->n_value
+ func_addr
;
9675 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
9678 last_line_num
= sym
->n_desc
;
9680 strcpy(last_func_name
, func_name
);
9684 str
= stabstr_section
->data
+ sym
->n_strx
;
9686 if (incl_index
< INCLUDE_STACK_SIZE
) {
9687 incl_files
[incl_index
++] = str
;
9695 if (sym
->n_strx
== 0) {
9696 incl_index
= 0; /* end of translation unit */
9698 str
= stabstr_section
->data
+ sym
->n_strx
;
9699 /* do not add path */
9701 if (len
> 0 && str
[len
- 1] != '/')
9709 /* second pass: we try symtab symbols (no line number info) */
9712 Elf32_Sym
*sym
, *sym_end
;
9715 sym_end
= (Elf32_Sym
*)(symtab_section
->data
+ symtab_section
->data_offset
);
9716 for(sym
= (Elf32_Sym
*)symtab_section
->data
+ 1;
9719 type
= ELF32_ST_TYPE(sym
->st_info
);
9720 if (type
== STT_FUNC
) {
9721 if (wanted_pc
>= sym
->st_value
&&
9722 wanted_pc
< sym
->st_value
+ sym
->st_size
) {
9723 pstrcpy(last_func_name
, sizeof(last_func_name
),
9724 strtab_section
->data
+ sym
->st_name
);
9730 /* did not find any info: */
9731 fprintf(stderr
, " ???\n");
9734 if (last_func_name
[0] != '\0') {
9735 fprintf(stderr
, " %s()", last_func_name
);
9737 if (incl_index
> 0) {
9738 fprintf(stderr
, " (%s:%d",
9739 incl_files
[incl_index
- 1], last_line_num
);
9740 for(i
= incl_index
- 2; i
>= 0; i
--)
9741 fprintf(stderr
, ", included from %s", incl_files
[i
]);
9742 fprintf(stderr
, ")");
9744 fprintf(stderr
, "\n");
9747 #if !defined(_WIN32) && !defined(CONFIG_TCCBOOT)
9751 /* fix for glibc 2.1 */
9757 /* return the PC at frame level 'level'. Return non zero if not found */
9758 static int rt_get_caller_pc(unsigned long *paddr
,
9759 ucontext_t
*uc
, int level
)
9765 #if defined(__FreeBSD__)
9766 *paddr
= uc
->uc_mcontext
.mc_eip
;
9767 #elif defined(__dietlibc__)
9768 *paddr
= uc
->uc_mcontext
.eip
;
9770 *paddr
= uc
->uc_mcontext
.gregs
[REG_EIP
];
9774 #if defined(__FreeBSD__)
9775 fp
= uc
->uc_mcontext
.mc_ebp
;
9776 #elif defined(__dietlibc__)
9777 fp
= uc
->uc_mcontext
.ebp
;
9779 fp
= uc
->uc_mcontext
.gregs
[REG_EBP
];
9781 for(i
=1;i
<level
;i
++) {
9782 /* XXX: check address validity with program info */
9783 if (fp
<= 0x1000 || fp
>= 0xc0000000)
9785 fp
= ((unsigned long *)fp
)[0];
9787 *paddr
= ((unsigned long *)fp
)[1];
9793 #warning add arch specific rt_get_caller_pc()
9795 static int rt_get_caller_pc(unsigned long *paddr
,
9796 ucontext_t
*uc
, int level
)
9802 /* emit a run time error at position 'pc' */
9803 void rt_error(ucontext_t
*uc
, const char *fmt
, ...)
9810 fprintf(stderr
, "Runtime error: ");
9811 vfprintf(stderr
, fmt
, ap
);
9812 fprintf(stderr
, "\n");
9813 for(i
=0;i
<num_callers
;i
++) {
9814 if (rt_get_caller_pc(&pc
, uc
, i
) < 0)
9817 fprintf(stderr
, "at ");
9819 fprintf(stderr
, "by ");
9826 /* signal handler for fatal errors */
9827 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
9829 ucontext_t
*uc
= puc
;
9833 switch(siginf
->si_code
) {
9836 rt_error(uc
, "division by zero");
9839 rt_error(uc
, "floating point exception");
9845 if (rt_bound_error_msg
&& *rt_bound_error_msg
)
9846 rt_error(uc
, *rt_bound_error_msg
);
9848 rt_error(uc
, "dereferencing invalid pointer");
9851 rt_error(uc
, "illegal instruction");
9854 rt_error(uc
, "abort() called");
9857 rt_error(uc
, "caught signal %d", signum
);
9864 /* do all relocations (needed before using tcc_get_symbol()) */
9865 int tcc_relocate(TCCState
*s1
)
9872 #ifdef TCC_TARGET_PE
9875 tcc_add_runtime(s1
);
9878 relocate_common_syms();
9880 tcc_add_linker_symbols(s1
);
9882 build_got_entries(s1
);
9884 /* compute relocation address : section are relocated in place. We
9885 also alloc the bss space */
9886 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9887 s
= s1
->sections
[i
];
9888 if (s
->sh_flags
& SHF_ALLOC
) {
9889 if (s
->sh_type
== SHT_NOBITS
)
9890 s
->data
= tcc_mallocz(s
->data_offset
);
9891 s
->sh_addr
= (unsigned long)s
->data
;
9895 relocate_syms(s1
, 1);
9897 if (s1
->nb_errors
!= 0)
9900 /* relocate each section */
9901 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9902 s
= s1
->sections
[i
];
9904 relocate_section(s1
, s
);
9907 /* mark executable sections as executable in memory */
9908 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9909 s
= s1
->sections
[i
];
9910 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_EXECINSTR
)) ==
9911 (SHF_ALLOC
| SHF_EXECINSTR
))
9912 set_pages_executable(s
->data
, s
->data_offset
);
9917 /* launch the compiled program with the given arguments */
9918 int tcc_run(TCCState
*s1
, int argc
, char **argv
)
9920 int (*prog_main
)(int, char **);
9922 if (tcc_relocate(s1
) < 0)
9925 prog_main
= tcc_get_symbol_err(s1
, "main");
9928 #if defined(_WIN32) || defined(CONFIG_TCCBOOT)
9929 error("debug mode currently not available for Windows");
9931 struct sigaction sigact
;
9932 /* install TCC signal handlers to print debug info on fatal
9934 sigact
.sa_flags
= SA_SIGINFO
| SA_RESETHAND
;
9935 sigact
.sa_sigaction
= sig_error
;
9936 sigemptyset(&sigact
.sa_mask
);
9937 sigaction(SIGFPE
, &sigact
, NULL
);
9938 sigaction(SIGILL
, &sigact
, NULL
);
9939 sigaction(SIGSEGV
, &sigact
, NULL
);
9940 sigaction(SIGBUS
, &sigact
, NULL
);
9941 sigaction(SIGABRT
, &sigact
, NULL
);
9945 #ifdef CONFIG_TCC_BCHECK
9946 if (do_bounds_check
) {
9947 void (*bound_init
)(void);
9949 /* set error function */
9950 rt_bound_error_msg
= (void *)tcc_get_symbol_err(s1
,
9951 "__bound_error_msg");
9953 /* XXX: use .init section so that it also work in binary ? */
9954 bound_init
= (void *)tcc_get_symbol_err(s1
, "__bound_init");
9958 return (*prog_main
)(argc
, argv
);
9961 TCCState
*tcc_new(void)
9968 s
= tcc_mallocz(sizeof(TCCState
));
9972 s
->output_type
= TCC_OUTPUT_MEMORY
;
9974 /* init isid table */
9976 isidnum_table
[i
] = isid(i
) || isnum(i
);
9978 /* add all tokens */
9980 memset(hash_ident
, 0, TOK_HASH_SIZE
* sizeof(TokenSym
*));
9982 tok_ident
= TOK_IDENT
;
9991 ts
= tok_alloc(p
, r
- p
- 1);
9995 /* we add dummy defines for some special macros to speed up tests
9996 and to have working defined() */
9997 define_push(TOK___LINE__
, MACRO_OBJ
, NULL
, NULL
);
9998 define_push(TOK___FILE__
, MACRO_OBJ
, NULL
, NULL
);
9999 define_push(TOK___DATE__
, MACRO_OBJ
, NULL
, NULL
);
10000 define_push(TOK___TIME__
, MACRO_OBJ
, NULL
, NULL
);
10002 /* standard defines */
10003 tcc_define_symbol(s
, "__STDC__", NULL
);
10004 #if defined(TCC_TARGET_I386)
10005 tcc_define_symbol(s
, "__i386__", NULL
);
10007 #if defined(TCC_TARGET_ARM)
10008 tcc_define_symbol(s
, "__ARM_ARCH_4__", NULL
);
10009 tcc_define_symbol(s
, "__arm_elf__", NULL
);
10010 tcc_define_symbol(s
, "__arm_elf", NULL
);
10011 tcc_define_symbol(s
, "arm_elf", NULL
);
10012 tcc_define_symbol(s
, "__arm__", NULL
);
10013 tcc_define_symbol(s
, "__arm", NULL
);
10014 tcc_define_symbol(s
, "arm", NULL
);
10015 tcc_define_symbol(s
, "__APCS_32__", NULL
);
10017 #ifdef TCC_TARGET_PE
10018 tcc_define_symbol(s
, "_WIN32", NULL
);
10020 tcc_define_symbol(s
, "__unix__", NULL
);
10021 tcc_define_symbol(s
, "__unix", NULL
);
10022 #if defined(__linux)
10023 tcc_define_symbol(s
, "__linux__", NULL
);
10024 tcc_define_symbol(s
, "__linux", NULL
);
10027 /* tiny C specific defines */
10028 tcc_define_symbol(s
, "__TINYC__", NULL
);
10030 /* tiny C & gcc defines */
10031 tcc_define_symbol(s
, "__SIZE_TYPE__", "unsigned int");
10032 tcc_define_symbol(s
, "__PTRDIFF_TYPE__", "int");
10033 #ifdef TCC_TARGET_PE
10034 tcc_define_symbol(s
, "__WCHAR_TYPE__", "unsigned short");
10036 tcc_define_symbol(s
, "__WCHAR_TYPE__", "int");
10039 /* default library paths */
10040 #ifdef TCC_TARGET_PE
10043 snprintf(buf
, sizeof(buf
), "%s/lib", tcc_lib_path
);
10044 tcc_add_library_path(s
, buf
);
10047 tcc_add_library_path(s
, "/usr/local/lib");
10048 tcc_add_library_path(s
, "/usr/lib");
10049 tcc_add_library_path(s
, "/lib");
10052 /* no section zero */
10053 dynarray_add((void ***)&s
->sections
, &s
->nb_sections
, NULL
);
10055 /* create standard sections */
10056 text_section
= new_section(s
, ".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
10057 data_section
= new_section(s
, ".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
10058 bss_section
= new_section(s
, ".bss", SHT_NOBITS
, SHF_ALLOC
| SHF_WRITE
);
10060 /* symbols are always generated for linking stage */
10061 symtab_section
= new_symtab(s
, ".symtab", SHT_SYMTAB
, 0,
10063 ".hashtab", SHF_PRIVATE
);
10064 strtab_section
= symtab_section
->link
;
10066 /* private symbol table for dynamic symbols */
10067 s
->dynsymtab_section
= new_symtab(s
, ".dynsymtab", SHT_SYMTAB
, SHF_PRIVATE
,
10069 ".dynhashtab", SHF_PRIVATE
);
10070 s
->alacarte_link
= 1;
10072 #ifdef CHAR_IS_UNSIGNED
10073 s
->char_is_unsigned
= 1;
10075 #if defined(TCC_TARGET_PE) && 0
10076 /* XXX: currently the PE linker is not ready to support that */
10077 s
->leading_underscore
= 1;
10082 void tcc_delete(TCCState
*s1
)
10086 /* free -D defines */
10087 free_defines(NULL
);
10090 n
= tok_ident
- TOK_IDENT
;
10091 for(i
= 0; i
< n
; i
++)
10092 tcc_free(table_ident
[i
]);
10093 tcc_free(table_ident
);
10095 /* free all sections */
10097 free_section(symtab_section
->hash
);
10099 free_section(s1
->dynsymtab_section
->hash
);
10100 free_section(s1
->dynsymtab_section
->link
);
10101 free_section(s1
->dynsymtab_section
);
10103 for(i
= 1; i
< s1
->nb_sections
; i
++)
10104 free_section(s1
->sections
[i
]);
10105 tcc_free(s1
->sections
);
10107 /* free loaded dlls array */
10108 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++)
10109 tcc_free(s1
->loaded_dlls
[i
]);
10110 tcc_free(s1
->loaded_dlls
);
10112 /* library paths */
10113 for(i
= 0; i
< s1
->nb_library_paths
; i
++)
10114 tcc_free(s1
->library_paths
[i
]);
10115 tcc_free(s1
->library_paths
);
10117 /* cached includes */
10118 for(i
= 0; i
< s1
->nb_cached_includes
; i
++)
10119 tcc_free(s1
->cached_includes
[i
]);
10120 tcc_free(s1
->cached_includes
);
10122 for(i
= 0; i
< s1
->nb_include_paths
; i
++)
10123 tcc_free(s1
->include_paths
[i
]);
10124 tcc_free(s1
->include_paths
);
10126 for(i
= 0; i
< s1
->nb_sysinclude_paths
; i
++)
10127 tcc_free(s1
->sysinclude_paths
[i
]);
10128 tcc_free(s1
->sysinclude_paths
);
10133 int tcc_add_include_path(TCCState
*s1
, const char *pathname
)
10137 pathname1
= tcc_strdup(pathname
);
10138 dynarray_add((void ***)&s1
->include_paths
, &s1
->nb_include_paths
, pathname1
);
10142 int tcc_add_sysinclude_path(TCCState
*s1
, const char *pathname
)
10146 pathname1
= tcc_strdup(pathname
);
10147 dynarray_add((void ***)&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
, pathname1
);
10151 static int tcc_add_file_internal(TCCState
*s1
, const char *filename
, int flags
)
10153 const char *ext
, *filename1
;
10156 BufferedFile
*saved_file
;
10158 /* find source file type with extension */
10159 filename1
= strrchr(filename
, '/');
10163 filename1
= filename
;
10164 ext
= strrchr(filename1
, '.');
10168 /* open the file */
10170 file
= tcc_open(s1
, filename
);
10172 if (flags
& AFF_PRINT_ERROR
) {
10173 error_noabort("file '%s' not found", filename
);
10179 if (flags
& AFF_PREPROCESS
) {
10180 ret
= tcc_preprocess(s1
);
10181 } else if (!ext
|| !strcmp(ext
, "c")) {
10182 /* C file assumed */
10183 ret
= tcc_compile(s1
);
10185 #ifdef CONFIG_TCC_ASM
10186 if (!strcmp(ext
, "S")) {
10187 /* preprocessed assembler */
10188 ret
= tcc_assemble(s1
, 1);
10189 } else if (!strcmp(ext
, "s")) {
10190 /* non preprocessed assembler */
10191 ret
= tcc_assemble(s1
, 0);
10194 #ifdef TCC_TARGET_PE
10195 if (!strcmp(ext
, "def")) {
10196 ret
= pe_load_def_file(s1
, fdopen(file
->fd
, "rb"));
10201 /* assume executable format: auto guess file type */
10202 ret
= read(fd
, &ehdr
, sizeof(ehdr
));
10203 lseek(fd
, 0, SEEK_SET
);
10205 error_noabort("could not read header");
10207 } else if (ret
!= sizeof(ehdr
)) {
10208 goto try_load_script
;
10211 if (ehdr
.e_ident
[0] == ELFMAG0
&&
10212 ehdr
.e_ident
[1] == ELFMAG1
&&
10213 ehdr
.e_ident
[2] == ELFMAG2
&&
10214 ehdr
.e_ident
[3] == ELFMAG3
) {
10215 file
->line_num
= 0; /* do not display line number if error */
10216 if (ehdr
.e_type
== ET_REL
) {
10217 ret
= tcc_load_object_file(s1
, fd
, 0);
10218 } else if (ehdr
.e_type
== ET_DYN
) {
10219 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
10220 #ifdef TCC_TARGET_PE
10224 h
= dlopen(filename
, RTLD_GLOBAL
| RTLD_LAZY
);
10231 ret
= tcc_load_dll(s1
, fd
, filename
,
10232 (flags
& AFF_REFERENCED_DLL
) != 0);
10235 error_noabort("unrecognized ELF file");
10238 } else if (memcmp((char *)&ehdr
, ARMAG
, 8) == 0) {
10239 file
->line_num
= 0; /* do not display line number if error */
10240 ret
= tcc_load_archive(s1
, fd
);
10242 #ifdef TCC_TARGET_COFF
10243 if (*(uint16_t *)(&ehdr
) == COFF_C67_MAGIC
) {
10244 ret
= tcc_load_coff(s1
, fd
);
10248 /* as GNU ld, consider it is an ld script if not recognized */
10250 ret
= tcc_load_ldscript(s1
);
10252 error_noabort("unrecognized file type");
10267 int tcc_add_file(TCCState
*s
, const char *filename
)
10269 return tcc_add_file_internal(s
, filename
, AFF_PRINT_ERROR
);
10272 int tcc_add_library_path(TCCState
*s
, const char *pathname
)
10276 pathname1
= tcc_strdup(pathname
);
10277 dynarray_add((void ***)&s
->library_paths
, &s
->nb_library_paths
, pathname1
);
10281 /* find and load a dll. Return non zero if not found */
10282 /* XXX: add '-rpath' option support ? */
10283 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
)
10288 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
10289 snprintf(buf
, sizeof(buf
), "%s/%s",
10290 s
->library_paths
[i
], filename
);
10291 if (tcc_add_file_internal(s
, buf
, flags
) == 0)
10297 /* the library name is the same as the argument of the '-l' option */
10298 int tcc_add_library(TCCState
*s
, const char *libraryname
)
10303 /* first we look for the dynamic library if not static linking */
10304 if (!s
->static_link
) {
10305 #ifdef TCC_TARGET_PE
10306 snprintf(buf
, sizeof(buf
), "%s.def", libraryname
);
10308 snprintf(buf
, sizeof(buf
), "lib%s.so", libraryname
);
10310 if (tcc_add_dll(s
, buf
, 0) == 0)
10314 /* then we look for the static library */
10315 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
10316 snprintf(buf
, sizeof(buf
), "%s/lib%s.a",
10317 s
->library_paths
[i
], libraryname
);
10318 if (tcc_add_file_internal(s
, buf
, 0) == 0)
10324 int tcc_add_symbol(TCCState
*s
, const char *name
, unsigned long val
)
10326 add_elf_sym(symtab_section
, val
, 0,
10327 ELF32_ST_INFO(STB_GLOBAL
, STT_NOTYPE
), 0,
10332 int tcc_set_output_type(TCCState
*s
, int output_type
)
10334 s
->output_type
= output_type
;
10336 if (!s
->nostdinc
) {
10339 /* default include paths */
10340 /* XXX: reverse order needed if -isystem support */
10341 #ifndef TCC_TARGET_PE
10342 tcc_add_sysinclude_path(s
, "/usr/local/include");
10343 tcc_add_sysinclude_path(s
, "/usr/include");
10345 snprintf(buf
, sizeof(buf
), "%s/include", tcc_lib_path
);
10346 tcc_add_sysinclude_path(s
, buf
);
10347 #ifdef TCC_TARGET_PE
10348 snprintf(buf
, sizeof(buf
), "%s/include/winapi", tcc_lib_path
);
10349 tcc_add_sysinclude_path(s
, buf
);
10353 /* if bound checking, then add corresponding sections */
10354 #ifdef CONFIG_TCC_BCHECK
10355 if (do_bounds_check
) {
10356 /* define symbol */
10357 tcc_define_symbol(s
, "__BOUNDS_CHECKING_ON", NULL
);
10358 /* create bounds sections */
10359 bounds_section
= new_section(s
, ".bounds",
10360 SHT_PROGBITS
, SHF_ALLOC
);
10361 lbounds_section
= new_section(s
, ".lbounds",
10362 SHT_PROGBITS
, SHF_ALLOC
);
10366 if (s
->char_is_unsigned
) {
10367 tcc_define_symbol(s
, "__CHAR_UNSIGNED__", NULL
);
10370 /* add debug sections */
10373 stab_section
= new_section(s
, ".stab", SHT_PROGBITS
, 0);
10374 stab_section
->sh_entsize
= sizeof(Stab_Sym
);
10375 stabstr_section
= new_section(s
, ".stabstr", SHT_STRTAB
, 0);
10376 put_elf_str(stabstr_section
, "");
10377 stab_section
->link
= stabstr_section
;
10378 /* put first entry */
10379 put_stabs("", 0, 0, 0, 0);
10382 /* add libc crt1/crti objects */
10383 #ifndef TCC_TARGET_PE
10384 if ((output_type
== TCC_OUTPUT_EXE
|| output_type
== TCC_OUTPUT_DLL
) &&
10386 if (output_type
!= TCC_OUTPUT_DLL
)
10387 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crt1.o");
10388 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crti.o");
10394 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10395 #define FD_INVERT 0x0002 /* invert value before storing */
10397 typedef struct FlagDef
{
10403 static const FlagDef warning_defs
[] = {
10404 { offsetof(TCCState
, warn_unsupported
), 0, "unsupported" },
10405 { offsetof(TCCState
, warn_write_strings
), 0, "write-strings" },
10406 { offsetof(TCCState
, warn_error
), 0, "error" },
10407 { offsetof(TCCState
, warn_implicit_function_declaration
), WD_ALL
,
10408 "implicit-function-declaration" },
10411 static int set_flag(TCCState
*s
, const FlagDef
*flags
, int nb_flags
,
10412 const char *name
, int value
)
10419 if (r
[0] == 'n' && r
[1] == 'o' && r
[2] == '-') {
10423 for(i
= 0, p
= flags
; i
< nb_flags
; i
++, p
++) {
10424 if (!strcmp(r
, p
->name
))
10429 if (p
->flags
& FD_INVERT
)
10431 *(int *)((uint8_t *)s
+ p
->offset
) = value
;
10436 /* set/reset a warning */
10437 int tcc_set_warning(TCCState
*s
, const char *warning_name
, int value
)
10442 if (!strcmp(warning_name
, "all")) {
10443 for(i
= 0, p
= warning_defs
; i
< countof(warning_defs
); i
++, p
++) {
10444 if (p
->flags
& WD_ALL
)
10445 *(int *)((uint8_t *)s
+ p
->offset
) = 1;
10449 return set_flag(s
, warning_defs
, countof(warning_defs
),
10450 warning_name
, value
);
10454 static const FlagDef flag_defs
[] = {
10455 { offsetof(TCCState
, char_is_unsigned
), 0, "unsigned-char" },
10456 { offsetof(TCCState
, char_is_unsigned
), FD_INVERT
, "signed-char" },
10457 { offsetof(TCCState
, nocommon
), FD_INVERT
, "common" },
10458 { offsetof(TCCState
, leading_underscore
), 0, "leading-underscore" },
10461 /* set/reset a flag */
10462 int tcc_set_flag(TCCState
*s
, const char *flag_name
, int value
)
10464 return set_flag(s
, flag_defs
, countof(flag_defs
),
10468 /* extract the basename of a file */
10469 static char *tcc_basename(const char *name
)
10471 char *p
= strchr(name
, 0);
10482 #if !defined(LIBTCC)
10484 static int64_t getclock_us(void)
10489 return (tb
.time
* 1000LL + tb
.millitm
) * 1000LL;
10492 gettimeofday(&tv
, NULL
);
10493 return tv
.tv_sec
* 1000000LL + tv
.tv_usec
;
10499 printf("tcc version " TCC_VERSION
" - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10500 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10501 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10502 " [infile1 infile2...] [-run infile args...]\n"
10504 "General options:\n"
10505 " -v display current version\n"
10506 " -c compile only - generate an object file\n"
10507 " -o outfile set output filename\n"
10508 " -Bdir set tcc internal library path\n"
10509 " -bench output compilation statistics\n"
10510 " -run run compiled source\n"
10511 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10512 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10513 " -w disable all warnings\n"
10514 "Preprocessor options:\n"
10515 " -E preprocess only\n"
10516 " -Idir add include path 'dir'\n"
10517 " -Dsym[=val] define 'sym' with value 'val'\n"
10518 " -Usym undefine 'sym'\n"
10519 "Linker options:\n"
10520 " -Ldir add library path 'dir'\n"
10521 " -llib link with dynamic or static library 'lib'\n"
10522 " -shared generate a shared library\n"
10523 " -static static linking\n"
10524 " -rdynamic export all global symbols to dynamic linker\n"
10525 " -r relocatable output\n"
10526 "Debugger options:\n"
10527 " -g generate runtime debug info\n"
10528 #ifdef CONFIG_TCC_BCHECK
10529 " -b compile with built-in memory and bounds checker (implies -g)\n"
10531 " -bt N show N callers in stack traces\n"
10535 #define TCC_OPTION_HAS_ARG 0x0001
10536 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10538 typedef struct TCCOption
{
10566 TCC_OPTION_nostdinc
,
10567 TCC_OPTION_nostdlib
,
10568 TCC_OPTION_print_search_dirs
,
10569 TCC_OPTION_rdynamic
,
10577 static const TCCOption tcc_options
[] = {
10578 { "h", TCC_OPTION_HELP
, 0 },
10579 { "?", TCC_OPTION_HELP
, 0 },
10580 { "I", TCC_OPTION_I
, TCC_OPTION_HAS_ARG
},
10581 { "D", TCC_OPTION_D
, TCC_OPTION_HAS_ARG
},
10582 { "U", TCC_OPTION_U
, TCC_OPTION_HAS_ARG
},
10583 { "L", TCC_OPTION_L
, TCC_OPTION_HAS_ARG
},
10584 { "B", TCC_OPTION_B
, TCC_OPTION_HAS_ARG
},
10585 { "l", TCC_OPTION_l
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10586 { "bench", TCC_OPTION_bench
, 0 },
10587 { "bt", TCC_OPTION_bt
, TCC_OPTION_HAS_ARG
},
10588 #ifdef CONFIG_TCC_BCHECK
10589 { "b", TCC_OPTION_b
, 0 },
10591 { "g", TCC_OPTION_g
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10592 { "c", TCC_OPTION_c
, 0 },
10593 { "static", TCC_OPTION_static
, 0 },
10594 { "shared", TCC_OPTION_shared
, 0 },
10595 { "o", TCC_OPTION_o
, TCC_OPTION_HAS_ARG
},
10596 { "run", TCC_OPTION_run
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10597 { "rdynamic", TCC_OPTION_rdynamic
, 0 },
10598 { "r", TCC_OPTION_r
, 0 },
10599 { "Wl,", TCC_OPTION_Wl
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10600 { "W", TCC_OPTION_W
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10601 { "O", TCC_OPTION_O
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10602 { "m", TCC_OPTION_m
, TCC_OPTION_HAS_ARG
},
10603 { "f", TCC_OPTION_f
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10604 { "nostdinc", TCC_OPTION_nostdinc
, 0 },
10605 { "nostdlib", TCC_OPTION_nostdlib
, 0 },
10606 { "print-search-dirs", TCC_OPTION_print_search_dirs
, 0 },
10607 { "v", TCC_OPTION_v
, 0 },
10608 { "w", TCC_OPTION_w
, 0 },
10609 { "pipe", TCC_OPTION_pipe
, 0},
10610 { "E", TCC_OPTION_E
, 0},
10614 /* convert 'str' into an array of space separated strings */
10615 static int expand_args(char ***pargv
, const char *str
)
10624 while (is_space(*str
))
10629 while (*str
!= '\0' && !is_space(*str
))
10632 arg
= tcc_malloc(len
+ 1);
10633 memcpy(arg
, s1
, len
);
10635 dynarray_add((void ***)&argv
, &argc
, arg
);
10641 static char **files
;
10642 static int nb_files
, nb_libraries
;
10643 static int multiple_files
;
10644 static int print_search_dirs
;
10645 static int output_type
;
10646 static int reloc_output
;
10647 static const char *outfile
;
10649 int parse_args(TCCState
*s
, int argc
, char **argv
)
10652 const TCCOption
*popt
;
10653 const char *optarg
, *p1
, *r1
;
10658 if (optind
>= argc
) {
10659 if (nb_files
== 0 && !print_search_dirs
)
10664 r
= argv
[optind
++];
10666 /* add a new file */
10667 dynarray_add((void ***)&files
, &nb_files
, r
);
10668 if (!multiple_files
) {
10670 /* argv[0] will be this file */
10674 /* find option in table (match only the first chars */
10675 popt
= tcc_options
;
10679 error("invalid option -- '%s'", r
);
10692 if (popt
->flags
& TCC_OPTION_HAS_ARG
) {
10693 if (*r1
!= '\0' || (popt
->flags
& TCC_OPTION_NOSEP
)) {
10696 if (optind
>= argc
)
10697 error("argument to '%s' is missing", r
);
10698 optarg
= argv
[optind
++];
10706 switch(popt
->index
) {
10707 case TCC_OPTION_HELP
:
10712 if (tcc_add_include_path(s
, optarg
) < 0)
10713 error("too many include paths");
10718 sym
= (char *)optarg
;
10719 value
= strchr(sym
, '=');
10724 tcc_define_symbol(s
, sym
, value
);
10728 tcc_undefine_symbol(s
, optarg
);
10731 tcc_add_library_path(s
, optarg
);
10734 /* set tcc utilities path (mainly for tcc development) */
10735 tcc_lib_path
= optarg
;
10738 dynarray_add((void ***)&files
, &nb_files
, r
);
10741 case TCC_OPTION_bench
:
10744 case TCC_OPTION_bt
:
10745 num_callers
= atoi(optarg
);
10747 #ifdef CONFIG_TCC_BCHECK
10749 do_bounds_check
= 1;
10757 multiple_files
= 1;
10758 output_type
= TCC_OUTPUT_OBJ
;
10760 case TCC_OPTION_static
:
10761 s
->static_link
= 1;
10763 case TCC_OPTION_shared
:
10764 output_type
= TCC_OUTPUT_DLL
;
10767 multiple_files
= 1;
10771 /* generate a .o merging several output files */
10773 output_type
= TCC_OUTPUT_OBJ
;
10775 case TCC_OPTION_nostdinc
:
10778 case TCC_OPTION_nostdlib
:
10781 case TCC_OPTION_print_search_dirs
:
10782 print_search_dirs
= 1;
10784 case TCC_OPTION_run
:
10788 argc1
= expand_args(&argv1
, optarg
);
10790 parse_args(s
, argc1
, argv1
);
10792 multiple_files
= 0;
10793 output_type
= TCC_OUTPUT_MEMORY
;
10797 printf("tcc version %s\n", TCC_VERSION
);
10800 if (tcc_set_flag(s
, optarg
, 1) < 0 && s
->warn_unsupported
)
10801 goto unsupported_option
;
10804 if (tcc_set_warning(s
, optarg
, 1) < 0 &&
10805 s
->warn_unsupported
)
10806 goto unsupported_option
;
10811 case TCC_OPTION_rdynamic
:
10814 case TCC_OPTION_Wl
:
10817 if (strstart(optarg
, "-Ttext,", &p
)) {
10818 s
->text_addr
= strtoul(p
, NULL
, 16);
10819 s
->has_text_addr
= 1;
10820 } else if (strstart(optarg
, "--oformat,", &p
)) {
10821 if (strstart(p
, "elf32-", NULL
)) {
10822 s
->output_format
= TCC_OUTPUT_FORMAT_ELF
;
10823 } else if (!strcmp(p
, "binary")) {
10824 s
->output_format
= TCC_OUTPUT_FORMAT_BINARY
;
10826 #ifdef TCC_TARGET_COFF
10827 if (!strcmp(p
, "coff")) {
10828 s
->output_format
= TCC_OUTPUT_FORMAT_COFF
;
10832 error("target %s not found", p
);
10835 error("unsupported linker option '%s'", optarg
);
10840 output_type
= TCC_OUTPUT_PREPROCESS
;
10843 if (s
->warn_unsupported
) {
10844 unsupported_option
:
10845 warning("unsupported option '%s'", r
);
10854 int main(int argc
, char **argv
)
10858 int nb_objfiles
, ret
, optind
;
10859 char objfilename
[1024];
10860 int64_t start_time
= 0;
10863 tcc_lib_path
= w32_tcc_lib_path();
10867 output_type
= TCC_OUTPUT_EXE
;
10869 multiple_files
= 1;
10874 print_search_dirs
= 0;
10876 optind
= parse_args(s
, argc
- 1, argv
+ 1) + 1;
10878 if (print_search_dirs
) {
10879 /* enough for Linux kernel */
10880 printf("install: %s/\n", tcc_lib_path
);
10884 nb_objfiles
= nb_files
- nb_libraries
;
10886 /* if outfile provided without other options, we output an
10888 if (outfile
&& output_type
== TCC_OUTPUT_MEMORY
)
10889 output_type
= TCC_OUTPUT_EXE
;
10891 /* check -c consistency : only single file handled. XXX: checks file type */
10892 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
10893 /* accepts only a single input file */
10894 if (nb_objfiles
!= 1)
10895 error("cannot specify multiple files with -c");
10896 if (nb_libraries
!= 0)
10897 error("cannot specify libraries with -c");
10901 if (output_type
== TCC_OUTPUT_PREPROCESS
) {
10903 s
->outfile
= stdout
;
10905 s
->outfile
= fopen(outfile
, "wb");
10907 error("could not open '%s", outfile
);
10909 } else if (output_type
!= TCC_OUTPUT_MEMORY
) {
10911 /* compute default outfile name */
10912 pstrcpy(objfilename
, sizeof(objfilename
) - 1,
10914 tcc_basename(files
[0]));
10915 #ifdef TCC_TARGET_PE
10916 pe_guess_outfile(objfilename
, output_type
);
10918 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
10919 char *ext
= strrchr(objfilename
, '.');
10921 goto default_outfile
;
10922 /* add .o extension */
10923 strcpy(ext
+ 1, "o");
10926 pstrcpy(objfilename
, sizeof(objfilename
), "a.out");
10929 outfile
= objfilename
;
10934 start_time
= getclock_us();
10937 tcc_set_output_type(s
, output_type
);
10939 /* compile or add each files or library */
10940 for(i
= 0;i
< nb_files
; i
++) {
10941 const char *filename
;
10943 filename
= files
[i
];
10944 if (output_type
== TCC_OUTPUT_PREPROCESS
) {
10945 tcc_add_file_internal(s
, filename
,
10946 AFF_PRINT_ERROR
| AFF_PREPROCESS
);
10948 if (filename
[0] == '-') {
10949 if (tcc_add_library(s
, filename
+ 2) < 0)
10950 error("cannot find %s", filename
);
10952 if (tcc_add_file(s
, filename
) < 0) {
10960 /* free all files */
10965 total_time
= (double)(getclock_us() - start_time
) / 1000000.0;
10966 if (total_time
< 0.001)
10967 total_time
= 0.001;
10968 if (total_bytes
< 1)
10970 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10971 tok_ident
- TOK_IDENT
, total_lines
, total_bytes
,
10972 total_time
, (int)(total_lines
/ total_time
),
10973 total_bytes
/ total_time
/ 1000000.0);
10976 if (s
->output_type
== TCC_OUTPUT_PREPROCESS
) {
10978 fclose(s
->outfile
);
10980 } else if (s
->output_type
== TCC_OUTPUT_MEMORY
) {
10981 ret
= tcc_run(s
, argc
- optind
, argv
+ optind
);
10983 #ifdef TCC_TARGET_PE
10984 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
10985 ret
= tcc_output_pe(s
, outfile
);
10989 ret
= tcc_output_file(s
, outfile
) ? 1 : 0;
10992 /* XXX: cannot do it with bound checking because of the malloc hooks */
10993 if (!do_bounds_check
)
10998 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size
, mem_max_size
);