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 */
325 static int *macro_ptr
, *macro_ptr_allocated
;
326 static int *unget_saved_macro_ptr
;
327 static int unget_saved_buffer
[TOK_MAX_SIZE
+ 1];
328 static int unget_buffer_enabled
;
329 static int parse_flags
;
330 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
331 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
332 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
333 token. line feed is also
335 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
337 static Section
*text_section
, *data_section
, *bss_section
; /* predefined sections */
338 static Section
*cur_text_section
; /* current section where function code is
340 #ifdef CONFIG_TCC_ASM
341 static Section
*last_text_section
; /* to handle .previous asm directive */
343 /* bound check related sections */
344 static Section
*bounds_section
; /* contains global data bound description */
345 static Section
*lbounds_section
; /* contains local data bound description */
346 /* symbol sections */
347 static Section
*symtab_section
, *strtab_section
;
350 static Section
*stab_section
, *stabstr_section
;
352 /* loc : local variable index
353 ind : output code index
355 anon_sym: anonymous symbol index
357 static int rsym
, anon_sym
, ind
, loc
;
358 /* expression generation modifiers */
359 static int const_wanted
; /* true if constant wanted */
360 static int nocode_wanted
; /* true if no code generation wanted for an expression */
361 static int global_expr
; /* true if compound literals must be allocated
362 globally (used during initializers parsing */
363 static CType func_vt
; /* current function return type (used by return
366 static int last_line_num
, last_ind
, func_ind
; /* debug last line number and pc */
367 static int tok_ident
;
368 static TokenSym
**table_ident
;
369 static TokenSym
*hash_ident
[TOK_HASH_SIZE
];
370 static char token_buf
[STRING_MAX_SIZE
+ 1];
371 static char *funcname
;
372 static Sym
*global_stack
, *local_stack
;
373 static Sym
*define_stack
;
374 static Sym
*global_label_stack
, *local_label_stack
;
375 /* symbol allocator */
376 #define SYM_POOL_NB (8192 / sizeof(Sym))
377 static Sym
*sym_free_first
;
379 static SValue vstack
[VSTACK_SIZE
], *vtop
;
380 /* some predefined types */
381 static CType char_pointer_type
, func_old_type
, int_type
;
382 /* true if isid(c) || isnum(c) */
383 static unsigned char isidnum_table
[256];
385 /* compile with debug symbol (and use them if error during execution) */
386 static int do_debug
= 0;
388 /* compile with built-in memory and bounds checker */
389 static int do_bounds_check
= 0;
391 /* display benchmark infos */
393 static int do_bench
= 0;
395 static int total_lines
;
396 static int total_bytes
;
398 /* use GNU C extensions */
399 static int gnu_ext
= 1;
401 /* use Tiny C extensions */
402 static int tcc_ext
= 1;
404 /* max number of callers shown if error */
405 static int num_callers
= 6;
406 static const char **rt_bound_error_msg
;
408 /* XXX: get rid of this ASAP */
409 static struct TCCState
*tcc_state
;
411 /* give the path of the tcc libraries */
412 static const char *tcc_lib_path
= CONFIG_TCCDIR
;
417 BufferedFile
**include_stack_ptr
;
418 int *ifdef_stack_ptr
;
420 /* include file handling */
421 char **include_paths
;
422 int nb_include_paths
;
423 char **sysinclude_paths
;
424 int nb_sysinclude_paths
;
425 CachedInclude
**cached_includes
;
426 int nb_cached_includes
;
428 char **library_paths
;
429 int nb_library_paths
;
431 /* array of all loaded dlls (including those referenced by loaded
433 DLLReference
**loaded_dlls
;
438 int nb_sections
; /* number of sections, including first dummy section */
443 unsigned long *got_offsets
;
445 /* give the correspondance from symtab indexes to dynsym indexes */
446 int *symtab_to_dynsym
;
448 /* temporary dynamic symbol sections (for dll loading) */
449 Section
*dynsymtab_section
;
450 /* exported dynamic symbol section */
453 int nostdinc
; /* if true, no standard headers are added */
454 int nostdlib
; /* if true, no standard libraries are added */
456 int nocommon
; /* if true, do not use common symbols for .bss data */
458 /* if true, static linking is performed */
461 /* if true, all symbols are exported */
464 /* if true, only link in referenced objects from archive */
467 /* address of text section */
468 unsigned long text_addr
;
471 /* output format, see TCC_OUTPUT_FORMAT_xxx */
474 /* C language options */
475 int char_is_unsigned
;
476 int leading_underscore
;
478 /* warning switches */
479 int warn_write_strings
;
480 int warn_unsupported
;
483 int warn_implicit_function_declaration
;
487 void (*error_func
)(void *opaque
, const char *msg
);
488 int error_set_jmp_enabled
;
489 jmp_buf error_jmp_buf
;
492 /* tiny assembler state */
495 /* see include_stack_ptr */
496 BufferedFile
*include_stack
[INCLUDE_STACK_SIZE
];
498 /* see ifdef_stack_ptr */
499 int ifdef_stack
[IFDEF_STACK_SIZE
];
501 /* see cached_includes */
502 int cached_includes_hash
[CACHED_INCLUDES_HASH_SIZE
];
505 int pack_stack
[PACK_STACK_SIZE
];
508 /* output file for preprocessing */
512 /* The current value can be: */
513 #define VT_VALMASK 0x00ff
514 #define VT_CONST 0x00f0 /* constant in vc
515 (must be first non register value) */
516 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
517 #define VT_LOCAL 0x00f2 /* offset on stack */
518 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
519 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
520 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
521 #define VT_LVAL 0x0100 /* var is an lvalue */
522 #define VT_SYM 0x0200 /* a symbol value is added */
523 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
524 char/short stored in integer registers) */
525 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
526 dereferencing value */
527 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
528 bounding function call point is in vc */
529 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
530 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
531 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
532 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
535 #define VT_INT 0 /* integer type */
536 #define VT_BYTE 1 /* signed byte type */
537 #define VT_SHORT 2 /* short type */
538 #define VT_VOID 3 /* void type */
539 #define VT_PTR 4 /* pointer */
540 #define VT_ENUM 5 /* enum definition */
541 #define VT_FUNC 6 /* function type */
542 #define VT_STRUCT 7 /* struct/union definition */
543 #define VT_FLOAT 8 /* IEEE float */
544 #define VT_DOUBLE 9 /* IEEE double */
545 #define VT_LDOUBLE 10 /* IEEE long double */
546 #define VT_BOOL 11 /* ISOC99 boolean type */
547 #define VT_LLONG 12 /* 64 bit integer */
548 #define VT_LONG 13 /* long integer (NEVER USED as type, only
550 #define VT_BTYPE 0x000f /* mask for basic type */
551 #define VT_UNSIGNED 0x0010 /* unsigned type */
552 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
553 #define VT_BITFIELD 0x0040 /* bitfield modifier */
554 #define VT_CONSTANT 0x0800 /* const modifier */
555 #define VT_VOLATILE 0x1000 /* volatile modifier */
556 #define VT_SIGNED 0x2000 /* signed type */
559 #define VT_EXTERN 0x00000080 /* extern definition */
560 #define VT_STATIC 0x00000100 /* static variable */
561 #define VT_TYPEDEF 0x00000200 /* typedef definition */
562 #define VT_INLINE 0x00000400 /* inline definition */
564 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
566 /* type mask (except storage) */
567 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
568 #define VT_TYPE (~(VT_STORAGE))
572 /* warning: the following compare tokens depend on i386 asm code */
584 #define TOK_LAND 0xa0
588 #define TOK_MID 0xa3 /* inc/dec, to void constant */
590 #define TOK_UDIV 0xb0 /* unsigned division */
591 #define TOK_UMOD 0xb1 /* unsigned modulo */
592 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
593 #define TOK_CINT 0xb3 /* number in tokc */
594 #define TOK_CCHAR 0xb4 /* char constant in tokc */
595 #define TOK_STR 0xb5 /* pointer to string in tokc */
596 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
597 #define TOK_LCHAR 0xb7
598 #define TOK_LSTR 0xb8
599 #define TOK_CFLOAT 0xb9 /* float constant */
600 #define TOK_LINENUM 0xba /* line number info */
601 #define TOK_CDOUBLE 0xc0 /* double constant */
602 #define TOK_CLDOUBLE 0xc1 /* long double constant */
603 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
604 #define TOK_ADDC1 0xc3 /* add with carry generation */
605 #define TOK_ADDC2 0xc4 /* add with carry use */
606 #define TOK_SUBC1 0xc5 /* add with carry generation */
607 #define TOK_SUBC2 0xc6 /* add with carry use */
608 #define TOK_CUINT 0xc8 /* unsigned int constant */
609 #define TOK_CLLONG 0xc9 /* long long constant */
610 #define TOK_CULLONG 0xca /* unsigned long long constant */
611 #define TOK_ARROW 0xcb
612 #define TOK_DOTS 0xcc /* three dots */
613 #define TOK_SHR 0xcd /* unsigned shift right */
614 #define TOK_PPNUM 0xce /* preprocessor number */
616 #define TOK_SHL 0x01 /* shift left */
617 #define TOK_SAR 0x02 /* signed shift right */
619 /* assignement operators : normal operator or 0x80 */
620 #define TOK_A_MOD 0xa5
621 #define TOK_A_AND 0xa6
622 #define TOK_A_MUL 0xaa
623 #define TOK_A_ADD 0xab
624 #define TOK_A_SUB 0xad
625 #define TOK_A_DIV 0xaf
626 #define TOK_A_XOR 0xde
627 #define TOK_A_OR 0xfc
628 #define TOK_A_SHL 0x81
629 #define TOK_A_SAR 0x82
632 #define offsetof(type, field) ((size_t) &((type *)0)->field)
636 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
639 /* WARNING: the content of this string encodes token numbers */
640 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";
642 #define TOK_EOF (-1) /* end of file */
643 #define TOK_LINEFEED 10 /* line feed */
645 /* all identificators and strings have token above that */
646 #define TOK_IDENT 256
648 /* only used for i386 asm opcodes definitions */
649 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
652 DEF(TOK_ASM_ ## x ## b, #x "b") \
653 DEF(TOK_ASM_ ## x ## w, #x "w") \
654 DEF(TOK_ASM_ ## x ## l, #x "l") \
655 DEF(TOK_ASM_ ## x, #x)
658 DEF(TOK_ASM_ ## x ## w, #x "w") \
659 DEF(TOK_ASM_ ## x ## l, #x "l") \
660 DEF(TOK_ASM_ ## x, #x)
663 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
664 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
665 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
666 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
669 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
670 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
673 #define DEF_ASMTEST(x) \
705 #define TOK_ASM_int TOK_INT
708 TOK_LAST
= TOK_IDENT
- 1,
709 #define DEF(id, str) id,
714 static const char tcc_keywords
[] =
715 #define DEF(id, str) str "\0"
720 #define TOK_UIDENT TOK_DEFINE
723 int __stdcall
GetModuleFileNameA(void *, char *, int);
724 void *__stdcall
GetProcAddress(void *, const char *);
725 void *__stdcall
GetModuleHandleA(const char *);
726 void *__stdcall
LoadLibraryA(const char *);
727 int __stdcall
FreeConsole(void);
728 int __stdcall
VirtualProtect(void*,unsigned long,unsigned long,unsigned long*);
729 #define PAGE_EXECUTE_READWRITE 0x0040
731 #define snprintf _snprintf
732 #define vsnprintf _vsnprintf
734 #define strtold (long double)strtod
735 #define strtof (float)strtod
736 #define strtoll (long long)strtol
738 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__)
739 /* currently incorrect */
740 long double strtold(const char *nptr
, char **endptr
)
742 return (long double)strtod(nptr
, endptr
);
744 float strtof(const char *nptr
, char **endptr
)
746 return (float)strtod(nptr
, endptr
);
749 /* XXX: need to define this to use them in non ISOC99 context */
750 extern float strtof (const char *__nptr
, char **__endptr
);
751 extern long double strtold (const char *__nptr
, char **__endptr
);
754 static char *pstrcpy(char *buf
, int buf_size
, const char *s
);
755 static char *pstrcat(char *buf
, int buf_size
, const char *s
);
756 static char *tcc_basename(const char *name
);
758 static void next(void);
759 static void next_nomacro(void);
760 static void parse_expr_type(CType
*type
);
761 static void expr_type(CType
*type
);
762 static void unary_type(CType
*type
);
763 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
764 int case_reg
, int is_expr
);
765 static int expr_const(void);
766 static void expr_eq(void);
767 static void gexpr(void);
768 static void gen_inline_functions(void);
769 static void decl(int l
);
770 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
771 int first
, int size_only
);
772 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
773 int has_init
, int v
, int scope
);
775 void gv2(int rc1
, int rc2
);
776 void move_reg(int r
, int s
);
777 void save_regs(int n
);
778 void save_reg(int r
);
783 int get_reg_ex(int rc
,int rc2
);
786 struct macro_level
*prev
;
790 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
791 const int *macro_str
, struct macro_level
**can_read_stream
);
793 void force_charshort_cast(int t
);
794 static void gen_cast(CType
*type
);
796 static Sym
*sym_find(int v
);
797 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
);
800 static int type_size(CType
*type
, int *a
);
801 static inline CType
*pointed_type(CType
*type
);
802 static int pointed_size(CType
*type
);
803 static int lvalue_type(int t
);
804 static int parse_btype(CType
*type
, AttributeDef
*ad
);
805 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
);
806 static int compare_types(CType
*type1
, CType
*type2
, int unqualified
);
807 static int is_compatible_types(CType
*type1
, CType
*type2
);
808 static int is_compatible_parameter_types(CType
*type1
, CType
*type2
);
810 int ieee_finite(double d
);
811 void error(const char *fmt
, ...);
815 void lexpand_nr(void);
816 static void vpush_global_sym(CType
*type
, int v
);
817 void vset(CType
*type
, int r
, int v
);
818 void type_to_str(char *buf
, int buf_size
,
819 CType
*type
, const char *varstr
);
820 char *get_tok_str(int v
, CValue
*cv
);
821 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
822 unsigned long offset
, unsigned long size
);
823 static Sym
*external_global_sym(int v
, CType
*type
, int r
);
825 /* section generation */
826 static void section_realloc(Section
*sec
, unsigned long new_size
);
827 static void *section_ptr_add(Section
*sec
, unsigned long size
);
828 static void put_extern_sym(Sym
*sym
, Section
*section
,
829 unsigned long value
, unsigned long size
);
830 static void greloc(Section
*s
, Sym
*sym
, unsigned long addr
, int type
);
831 static int put_elf_str(Section
*s
, const char *sym
);
832 static int put_elf_sym(Section
*s
,
833 unsigned long value
, unsigned long size
,
834 int info
, int other
, int shndx
, const char *name
);
835 static int add_elf_sym(Section
*s
, unsigned long value
, unsigned long size
,
836 int info
, int other
, int sh_num
, const char *name
);
837 static void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
838 int type
, int symbol
);
839 static void put_stabs(const char *str
, int type
, int other
, int desc
,
840 unsigned long value
);
841 static void put_stabs_r(const char *str
, int type
, int other
, int desc
,
842 unsigned long value
, Section
*sec
, int sym_index
);
843 static void put_stabn(int type
, int other
, int desc
, int value
);
844 static void put_stabd(int type
, int other
, int desc
);
845 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
);
847 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
848 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
849 #define AFF_PREPROCESS 0x0004 /* preprocess file */
850 static int tcc_add_file_internal(TCCState
*s
, const char *filename
, int flags
);
853 int tcc_output_coff(TCCState
*s1
, FILE *f
);
856 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
);
857 int pe_load_def_file(struct TCCState
*s1
, FILE *fp
);
858 void pe_setup_paths(struct TCCState
*s1
, int *p_output_type
, const char **p_outfile
, char *first_file
);
859 unsigned long pe_add_runtime(struct TCCState
*s1
);
860 int tcc_output_pe(struct TCCState
*s1
, const char *filename
);
864 #ifdef CONFIG_TCC_ASM
866 typedef struct ExprValue
{
871 #define MAX_ASM_OPERANDS 30
873 typedef struct ASMOperand
{
874 int id
; /* GCC 3 optionnal identifier (0 if number only supported */
876 char asm_str
[16]; /* computed asm string for operand */
877 SValue
*vt
; /* C value of the expression */
878 int ref_index
; /* if >= 0, gives reference to a output constraint */
879 int input_index
; /* if >= 0, gives reference to an input constraint */
880 int priority
; /* priority, used to assign registers */
881 int reg
; /* if >= 0, register number used for this operand */
882 int is_llong
; /* true if double register value */
883 int is_memory
; /* true if memory operand */
884 int is_rw
; /* for '+' modifier */
887 static void asm_expr(TCCState
*s1
, ExprValue
*pe
);
888 static int asm_int_expr(TCCState
*s1
);
889 static int find_constraint(ASMOperand
*operands
, int nb_operands
,
890 const char *name
, const char **pp
);
892 static int tcc_assemble(TCCState
*s1
, int do_preprocess
);
896 static void asm_instr(void);
897 static void asm_global_instr(void);
899 /* true if float/double/long double type */
900 static inline int is_float(int t
)
904 return bt
== VT_LDOUBLE
|| bt
== VT_DOUBLE
|| bt
== VT_FLOAT
;
907 #ifdef TCC_TARGET_I386
908 #include "i386-gen.c"
911 #ifdef TCC_TARGET_ARM
915 #ifdef TCC_TARGET_C67
919 #ifdef CONFIG_TCC_STATIC
921 #define RTLD_LAZY 0x001
922 #define RTLD_NOW 0x002
923 #define RTLD_GLOBAL 0x100
924 #define RTLD_DEFAULT NULL
926 /* dummy function for profiling */
927 void *dlopen(const char *filename
, int flag
)
932 const char *dlerror(void)
937 typedef struct TCCSyms
{
942 #define TCCSYM(a) { #a, &a, },
944 /* add the symbol you want here if no dynamic linking is done */
945 static TCCSyms tcc_syms
[] = {
946 #if !defined(CONFIG_TCCBOOT)
955 void *resolve_sym(TCCState
*s1
, const char *symbol
, int type
)
959 while (p
->str
!= NULL
) {
960 if (!strcmp(p
->str
, symbol
))
967 #elif !defined(WIN32)
971 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
)
973 return dlsym(RTLD_DEFAULT
, sym
);
978 /********************************************************/
980 /* we use our own 'finite' function to avoid potential problems with
981 non standard math libs */
982 /* XXX: endianness dependent */
983 int ieee_finite(double d
)
986 return ((unsigned)((p
[1] | 0x800fffff) + 1)) >> 31;
989 /* copy a string and truncate it. */
990 static char *pstrcpy(char *buf
, int buf_size
, const char *s
)
997 q_end
= buf
+ buf_size
- 1;
1009 /* strcat and truncate. */
1010 static char *pstrcat(char *buf
, int buf_size
, const char *s
)
1015 pstrcpy(buf
+ len
, buf_size
- len
, s
);
1019 static int strstart(const char *str
, const char *val
, const char **ptr
)
1024 while (*q
!= '\0') {
1035 /* memory management */
1041 static inline void tcc_free(void *ptr
)
1044 mem_cur_size
-= malloc_usable_size(ptr
);
1049 static void *tcc_malloc(unsigned long size
)
1054 error("memory full");
1056 mem_cur_size
+= malloc_usable_size(ptr
);
1057 if (mem_cur_size
> mem_max_size
)
1058 mem_max_size
= mem_cur_size
;
1063 static void *tcc_mallocz(unsigned long size
)
1066 ptr
= tcc_malloc(size
);
1067 memset(ptr
, 0, size
);
1071 static inline void *tcc_realloc(void *ptr
, unsigned long size
)
1075 mem_cur_size
-= malloc_usable_size(ptr
);
1077 ptr1
= realloc(ptr
, size
);
1079 /* NOTE: count not correct if alloc error, but not critical */
1080 mem_cur_size
+= malloc_usable_size(ptr1
);
1081 if (mem_cur_size
> mem_max_size
)
1082 mem_max_size
= mem_cur_size
;
1087 static char *tcc_strdup(const char *str
)
1090 ptr
= tcc_malloc(strlen(str
) + 1);
1095 #define free(p) use_tcc_free(p)
1096 #define malloc(s) use_tcc_malloc(s)
1097 #define realloc(p, s) use_tcc_realloc(p, s)
1099 static void dynarray_add(void ***ptab
, int *nb_ptr
, void *data
)
1106 /* every power of two we double array size */
1107 if ((nb
& (nb
- 1)) == 0) {
1112 pp
= tcc_realloc(pp
, nb_alloc
* sizeof(void *));
1114 error("memory full");
1121 /* symbol allocator */
1122 static Sym
*__sym_malloc(void)
1124 Sym
*sym_pool
, *sym
, *last_sym
;
1127 sym_pool
= tcc_malloc(SYM_POOL_NB
* sizeof(Sym
));
1129 last_sym
= sym_free_first
;
1131 for(i
= 0; i
< SYM_POOL_NB
; i
++) {
1132 sym
->next
= last_sym
;
1136 sym_free_first
= last_sym
;
1140 static inline Sym
*sym_malloc(void)
1143 sym
= sym_free_first
;
1145 sym
= __sym_malloc();
1146 sym_free_first
= sym
->next
;
1150 static inline void sym_free(Sym
*sym
)
1152 sym
->next
= sym_free_first
;
1153 sym_free_first
= sym
;
1156 Section
*new_section(TCCState
*s1
, const char *name
, int sh_type
, int sh_flags
)
1160 sec
= tcc_mallocz(sizeof(Section
) + strlen(name
));
1161 strcpy(sec
->name
, name
);
1162 sec
->sh_type
= sh_type
;
1163 sec
->sh_flags
= sh_flags
;
1170 sec
->sh_addralign
= 4;
1173 sec
->sh_addralign
= 1;
1176 sec
->sh_addralign
= 32; /* default conservative alignment */
1180 /* only add section if not private */
1181 if (!(sh_flags
& SHF_PRIVATE
)) {
1182 sec
->sh_num
= s1
->nb_sections
;
1183 dynarray_add((void ***)&s1
->sections
, &s1
->nb_sections
, sec
);
1188 static void free_section(Section
*s
)
1194 /* realloc section and set its content to zero */
1195 static void section_realloc(Section
*sec
, unsigned long new_size
)
1198 unsigned char *data
;
1200 size
= sec
->data_allocated
;
1203 while (size
< new_size
)
1205 data
= tcc_realloc(sec
->data
, size
);
1207 error("memory full");
1208 memset(data
+ sec
->data_allocated
, 0, size
- sec
->data_allocated
);
1210 sec
->data_allocated
= size
;
1213 /* reserve at least 'size' bytes in section 'sec' from
1214 sec->data_offset. */
1215 static void *section_ptr_add(Section
*sec
, unsigned long size
)
1217 unsigned long offset
, offset1
;
1219 offset
= sec
->data_offset
;
1220 offset1
= offset
+ size
;
1221 if (offset1
> sec
->data_allocated
)
1222 section_realloc(sec
, offset1
);
1223 sec
->data_offset
= offset1
;
1224 return sec
->data
+ offset
;
1227 /* return a reference to a section, and create it if it does not
1229 Section
*find_section(TCCState
*s1
, const char *name
)
1233 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1234 sec
= s1
->sections
[i
];
1235 if (!strcmp(name
, sec
->name
))
1238 /* sections are created as PROGBITS */
1239 return new_section(s1
, name
, SHT_PROGBITS
, SHF_ALLOC
);
1242 #define SECTION_ABS ((void *)1)
1244 /* update sym->c so that it points to an external symbol in section
1245 'section' with value 'value' */
1246 static void put_extern_sym2(Sym
*sym
, Section
*section
,
1247 unsigned long value
, unsigned long size
,
1248 int can_add_underscore
)
1250 int sym_type
, sym_bind
, sh_num
, info
;
1255 if (section
== NULL
)
1257 else if (section
== SECTION_ABS
)
1260 sh_num
= section
->sh_num
;
1262 if ((sym
->type
.t
& VT_BTYPE
) == VT_FUNC
)
1263 sym_type
= STT_FUNC
;
1265 sym_type
= STT_OBJECT
;
1266 if (sym
->type
.t
& VT_STATIC
)
1267 sym_bind
= STB_LOCAL
;
1269 sym_bind
= STB_GLOBAL
;
1271 name
= get_tok_str(sym
->v
, NULL
);
1272 #ifdef CONFIG_TCC_BCHECK
1273 if (do_bounds_check
) {
1276 /* XXX: avoid doing that for statics ? */
1277 /* if bound checking is activated, we change some function
1278 names by adding the "__bound" prefix */
1281 /* XXX: we rely only on malloc hooks */
1294 strcpy(buf
, "__bound_");
1301 if (tcc_state
->leading_underscore
&& can_add_underscore
) {
1303 pstrcpy(buf1
+ 1, sizeof(buf1
) - 1, name
);
1306 info
= ELF32_ST_INFO(sym_bind
, sym_type
);
1307 sym
->c
= add_elf_sym(symtab_section
, value
, size
, info
, 0, sh_num
, name
);
1309 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
1310 esym
->st_value
= value
;
1311 esym
->st_size
= size
;
1312 esym
->st_shndx
= sh_num
;
1316 static void put_extern_sym(Sym
*sym
, Section
*section
,
1317 unsigned long value
, unsigned long size
)
1319 put_extern_sym2(sym
, section
, value
, size
, 1);
1322 /* add a new relocation entry to symbol 'sym' in section 's' */
1323 static void greloc(Section
*s
, Sym
*sym
, unsigned long offset
, int type
)
1326 put_extern_sym(sym
, NULL
, 0, 0);
1327 /* now we can add ELF relocation info */
1328 put_elf_reloc(symtab_section
, s
, offset
, type
, sym
->c
);
1331 static inline int isid(int c
)
1333 return (c
>= 'a' && c
<= 'z') ||
1334 (c
>= 'A' && c
<= 'Z') ||
1338 static inline int isnum(int c
)
1340 return c
>= '0' && c
<= '9';
1343 static inline int isoct(int c
)
1345 return c
>= '0' && c
<= '7';
1348 static inline int toup(int c
)
1350 if (c
>= 'a' && c
<= 'z')
1351 return c
- 'a' + 'A';
1356 static void strcat_vprintf(char *buf
, int buf_size
, const char *fmt
, va_list ap
)
1360 vsnprintf(buf
+ len
, buf_size
- len
, fmt
, ap
);
1363 static void strcat_printf(char *buf
, int buf_size
, const char *fmt
, ...)
1367 strcat_vprintf(buf
, buf_size
, fmt
, ap
);
1371 void error1(TCCState
*s1
, int is_warning
, const char *fmt
, va_list ap
)
1378 for(f
= s1
->include_stack
; f
< s1
->include_stack_ptr
; f
++)
1379 strcat_printf(buf
, sizeof(buf
), "In file included from %s:%d:\n",
1380 (*f
)->filename
, (*f
)->line_num
);
1381 if (file
->line_num
> 0) {
1382 strcat_printf(buf
, sizeof(buf
),
1383 "%s:%d: ", file
->filename
, file
->line_num
);
1385 strcat_printf(buf
, sizeof(buf
),
1386 "%s: ", file
->filename
);
1389 strcat_printf(buf
, sizeof(buf
),
1393 strcat_printf(buf
, sizeof(buf
), "warning: ");
1394 strcat_vprintf(buf
, sizeof(buf
), fmt
, ap
);
1396 if (!s1
->error_func
) {
1397 /* default case: stderr */
1398 fprintf(stderr
, "%s\n", buf
);
1400 s1
->error_func(s1
->error_opaque
, buf
);
1402 if (!is_warning
|| s1
->warn_error
)
1407 void tcc_set_error_func(TCCState
*s
, void *error_opaque
,
1408 void (*error_func
)(void *opaque
, const char *msg
))
1410 s
->error_opaque
= error_opaque
;
1411 s
->error_func
= error_func
;
1415 /* error without aborting current compilation */
1416 void error_noabort(const char *fmt
, ...)
1418 TCCState
*s1
= tcc_state
;
1422 error1(s1
, 0, fmt
, ap
);
1426 void error(const char *fmt
, ...)
1428 TCCState
*s1
= tcc_state
;
1432 error1(s1
, 0, fmt
, ap
);
1434 /* better than nothing: in some cases, we accept to handle errors */
1435 if (s1
->error_set_jmp_enabled
) {
1436 longjmp(s1
->error_jmp_buf
, 1);
1438 /* XXX: eliminate this someday */
1443 void expect(const char *msg
)
1445 error("%s expected", msg
);
1448 void warning(const char *fmt
, ...)
1450 TCCState
*s1
= tcc_state
;
1457 error1(s1
, 1, fmt
, ap
);
1464 error("'%c' expected", c
);
1468 static void test_lvalue(void)
1470 if (!(vtop
->r
& VT_LVAL
))
1474 /* allocate a new token */
1475 static TokenSym
*tok_alloc_new(TokenSym
**pts
, const char *str
, int len
)
1477 TokenSym
*ts
, **ptable
;
1480 if (tok_ident
>= SYM_FIRST_ANOM
)
1481 error("memory full");
1483 /* expand token table if needed */
1484 i
= tok_ident
- TOK_IDENT
;
1485 if ((i
% TOK_ALLOC_INCR
) == 0) {
1486 ptable
= tcc_realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
1488 error("memory full");
1489 table_ident
= ptable
;
1492 ts
= tcc_malloc(sizeof(TokenSym
) + len
);
1493 table_ident
[i
] = ts
;
1494 ts
->tok
= tok_ident
++;
1495 ts
->sym_define
= NULL
;
1496 ts
->sym_label
= NULL
;
1497 ts
->sym_struct
= NULL
;
1498 ts
->sym_identifier
= NULL
;
1500 ts
->hash_next
= NULL
;
1501 memcpy(ts
->str
, str
, len
);
1502 ts
->str
[len
] = '\0';
1507 #define TOK_HASH_INIT 1
1508 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1510 /* find a token and add it if not found */
1511 static TokenSym
*tok_alloc(const char *str
, int len
)
1513 TokenSym
*ts
, **pts
;
1519 h
= TOK_HASH_FUNC(h
, ((unsigned char *)str
)[i
]);
1520 h
&= (TOK_HASH_SIZE
- 1);
1522 pts
= &hash_ident
[h
];
1527 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
1529 pts
= &(ts
->hash_next
);
1531 return tok_alloc_new(pts
, str
, len
);
1534 /* CString handling */
1536 static void cstr_realloc(CString
*cstr
, int new_size
)
1541 size
= cstr
->size_allocated
;
1543 size
= 8; /* no need to allocate a too small first string */
1544 while (size
< new_size
)
1546 data
= tcc_realloc(cstr
->data_allocated
, size
);
1548 error("memory full");
1549 cstr
->data_allocated
= data
;
1550 cstr
->size_allocated
= size
;
1555 static inline void cstr_ccat(CString
*cstr
, int ch
)
1558 size
= cstr
->size
+ 1;
1559 if (size
> cstr
->size_allocated
)
1560 cstr_realloc(cstr
, size
);
1561 ((unsigned char *)cstr
->data
)[size
- 1] = ch
;
1565 static void cstr_cat(CString
*cstr
, const char *str
)
1577 /* add a wide char */
1578 static void cstr_wccat(CString
*cstr
, int ch
)
1581 size
= cstr
->size
+ sizeof(nwchar_t
);
1582 if (size
> cstr
->size_allocated
)
1583 cstr_realloc(cstr
, size
);
1584 *(nwchar_t
*)(((unsigned char *)cstr
->data
) + size
- sizeof(nwchar_t
)) = ch
;
1588 static void cstr_new(CString
*cstr
)
1590 memset(cstr
, 0, sizeof(CString
));
1593 /* free string and reset it to NULL */
1594 static void cstr_free(CString
*cstr
)
1596 tcc_free(cstr
->data_allocated
);
1600 #define cstr_reset(cstr) cstr_free(cstr)
1602 /* XXX: unicode ? */
1603 static void add_char(CString
*cstr
, int c
)
1605 if (c
== '\'' || c
== '\"' || c
== '\\') {
1606 /* XXX: could be more precise if char or string */
1607 cstr_ccat(cstr
, '\\');
1609 if (c
>= 32 && c
<= 126) {
1612 cstr_ccat(cstr
, '\\');
1614 cstr_ccat(cstr
, 'n');
1616 cstr_ccat(cstr
, '0' + ((c
>> 6) & 7));
1617 cstr_ccat(cstr
, '0' + ((c
>> 3) & 7));
1618 cstr_ccat(cstr
, '0' + (c
& 7));
1623 /* XXX: buffer overflow */
1624 /* XXX: float tokens */
1625 char *get_tok_str(int v
, CValue
*cv
)
1627 static char buf
[STRING_MAX_SIZE
+ 1];
1628 static CString cstr_buf
;
1634 /* NOTE: to go faster, we give a fixed buffer for small strings */
1635 cstr_reset(&cstr_buf
);
1636 cstr_buf
.data
= buf
;
1637 cstr_buf
.size_allocated
= sizeof(buf
);
1643 /* XXX: not quite exact, but only useful for testing */
1644 sprintf(p
, "%u", cv
->ui
);
1648 /* XXX: not quite exact, but only useful for testing */
1649 sprintf(p
, "%Lu", cv
->ull
);
1653 cstr_ccat(&cstr_buf
, '\'');
1654 add_char(&cstr_buf
, cv
->i
);
1655 cstr_ccat(&cstr_buf
, '\'');
1656 cstr_ccat(&cstr_buf
, '\0');
1660 len
= cstr
->size
- 1;
1662 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1663 cstr_ccat(&cstr_buf
, '\0');
1668 cstr_ccat(&cstr_buf
, '\"');
1670 len
= cstr
->size
- 1;
1672 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1674 len
= (cstr
->size
/ sizeof(nwchar_t
)) - 1;
1676 add_char(&cstr_buf
, ((nwchar_t
*)cstr
->data
)[i
]);
1678 cstr_ccat(&cstr_buf
, '\"');
1679 cstr_ccat(&cstr_buf
, '\0');
1688 return strcpy(p
, "...");
1690 return strcpy(p
, "<<=");
1692 return strcpy(p
, ">>=");
1694 if (v
< TOK_IDENT
) {
1695 /* search in two bytes table */
1709 } else if (v
< tok_ident
) {
1710 return table_ident
[v
- TOK_IDENT
]->str
;
1711 } else if (v
>= SYM_FIRST_ANOM
) {
1712 /* special name for anonymous symbol */
1713 sprintf(p
, "L.%u", v
- SYM_FIRST_ANOM
);
1715 /* should never happen */
1720 return cstr_buf
.data
;
1723 /* push, without hashing */
1724 static Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
1738 /* find a symbol and return its associated structure. 's' is the top
1739 of the symbol stack */
1740 static Sym
*sym_find2(Sym
*s
, int v
)
1750 /* structure lookup */
1751 static inline Sym
*struct_find(int v
)
1754 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1756 return table_ident
[v
]->sym_struct
;
1759 /* find an identifier */
1760 static inline Sym
*sym_find(int v
)
1763 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1765 return table_ident
[v
]->sym_identifier
;
1768 /* push a given symbol on the symbol stack */
1769 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
)
1778 s
= sym_push2(ps
, v
, type
->t
, c
);
1779 s
->type
.ref
= type
->ref
;
1781 /* don't record fields or anonymous symbols */
1783 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1784 /* record symbol in token array */
1785 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1787 ps
= &ts
->sym_struct
;
1789 ps
= &ts
->sym_identifier
;
1796 /* push a global identifier */
1797 static Sym
*global_identifier_push(int v
, int t
, int c
)
1800 s
= sym_push2(&global_stack
, v
, t
, c
);
1801 /* don't record anonymous symbol */
1802 if (v
< SYM_FIRST_ANOM
) {
1803 ps
= &table_ident
[v
- TOK_IDENT
]->sym_identifier
;
1804 /* modify the top most local identifier, so that
1805 sym_identifier will point to 's' when popped */
1807 ps
= &(*ps
)->prev_tok
;
1814 /* pop symbols until top reaches 'b' */
1815 static void sym_pop(Sym
**ptop
, Sym
*b
)
1825 /* remove symbol in token array */
1827 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1828 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1830 ps
= &ts
->sym_struct
;
1832 ps
= &ts
->sym_identifier
;
1843 BufferedFile
*tcc_open(TCCState
*s1
, const char *filename
)
1849 fd
= open(filename
, O_RDONLY
| O_BINARY
);
1852 bf
= tcc_malloc(sizeof(BufferedFile
));
1858 bf
->buf_ptr
= bf
->buffer
;
1859 bf
->buf_end
= bf
->buffer
;
1860 bf
->buffer
[0] = CH_EOB
; /* put eob symbol */
1861 pstrcpy(bf
->filename
, sizeof(bf
->filename
), filename
);
1862 len
= strlen(bf
->filename
);
1863 for (i
= 0; i
< len
; i
++)
1864 if (bf
->filename
[i
] == '\\')
1865 bf
->filename
[i
] = '/';
1867 bf
->ifndef_macro
= 0;
1868 bf
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
1869 // printf("opening '%s'\n", filename);
1873 void tcc_close(BufferedFile
*bf
)
1875 total_lines
+= bf
->line_num
;
1880 /* fill input buffer and peek next char */
1881 static int tcc_peekc_slow(BufferedFile
*bf
)
1884 /* only tries to read if really end of buffer */
1885 if (bf
->buf_ptr
>= bf
->buf_end
) {
1887 #if defined(PARSE_DEBUG)
1892 len
= read(bf
->fd
, bf
->buffer
, len
);
1899 bf
->buf_ptr
= bf
->buffer
;
1900 bf
->buf_end
= bf
->buffer
+ len
;
1901 *bf
->buf_end
= CH_EOB
;
1903 if (bf
->buf_ptr
< bf
->buf_end
) {
1904 return bf
->buf_ptr
[0];
1906 bf
->buf_ptr
= bf
->buf_end
;
1911 /* return the current character, handling end of block if necessary
1913 static int handle_eob(void)
1915 return tcc_peekc_slow(file
);
1918 /* read next char from current input file and handle end of input buffer */
1919 static inline void inp(void)
1921 ch
= *(++(file
->buf_ptr
));
1922 /* end of buffer/file handling */
1927 /* handle '\[\r]\n' */
1928 static void handle_stray(void)
1930 while (ch
== '\\') {
1935 } else if (ch
== '\r') {
1943 error("stray '\\' in program");
1948 /* skip the stray and handle the \\n case. Output an error if
1949 incorrect char after the stray */
1950 static int handle_stray1(uint8_t *p
)
1954 if (p
>= file
->buf_end
) {
1971 /* handle just the EOB case, but not stray */
1972 #define PEEKC_EOB(c, p)\
1983 /* handle the complicated stray case */
1984 #define PEEKC(c, p)\
1989 c = handle_stray1(p);\
1994 /* input with '\[\r]\n' handling. Note that this function cannot
1995 handle other characters after '\', so you cannot call it inside
1996 strings or comments */
1997 static void minp(void)
2005 /* single line C++ comments */
2006 static uint8_t *parse_line_comment(uint8_t *p
)
2014 if (c
== '\n' || c
== CH_EOF
) {
2016 } else if (c
== '\\') {
2025 } else if (c
== '\r') {
2043 static uint8_t *parse_comment(uint8_t *p
)
2049 /* fast skip loop */
2052 if (c
== '\n' || c
== '*' || c
== '\\')
2056 if (c
== '\n' || c
== '*' || c
== '\\')
2060 /* now we can handle all the cases */
2064 } else if (c
== '*') {
2070 } else if (c
== '/') {
2071 goto end_of_comment
;
2072 } else if (c
== '\\') {
2077 /* skip '\[\r]\n', otherwise just skip the stray */
2083 } else if (c
== '\r') {
2100 /* stray, eob or eof */
2105 error("unexpected end of file in comment");
2106 } else if (c
== '\\') {
2118 /* space exlcuding newline */
2119 static inline int is_space(int ch
)
2121 return ch
== ' ' || ch
== '\t' || ch
== '\v' || ch
== '\f' || ch
== '\r';
2124 static inline void skip_spaces(void)
2126 while (is_space(ch
))
2130 /* parse a string without interpreting escapes */
2131 static uint8_t *parse_pp_string(uint8_t *p
,
2132 int sep
, CString
*str
)
2140 } else if (c
== '\\') {
2145 unterminated_string
:
2146 /* XXX: indicate line number of start of string */
2147 error("missing terminating %c character", sep
);
2148 } else if (c
== '\\') {
2149 /* escape : just skip \[\r]\n */
2154 } else if (c
== '\r') {
2157 expect("'\n' after '\r'");
2160 } else if (c
== CH_EOF
) {
2161 goto unterminated_string
;
2164 cstr_ccat(str
, '\\');
2170 } else if (c
== '\n') {
2173 } else if (c
== '\r') {
2177 cstr_ccat(str
, '\r');
2193 /* skip block of text until #else, #elif or #endif. skip also pairs of
2195 void preprocess_skip(void)
2197 int a
, start_of_line
, c
;
2224 } else if (c
== '\\') {
2225 /* XXX: incorrect: should not give an error */
2226 ch
= file
->buf_ptr
[0];
2234 p
= parse_pp_string(p
, c
, NULL
);
2243 p
= parse_comment(p
);
2244 } else if (ch
== '/') {
2245 p
= parse_line_comment(p
);
2251 if (start_of_line
) {
2256 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
2258 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
2260 else if (tok
== TOK_ENDIF
)
2274 /* ParseState handling */
2276 /* XXX: currently, no include file info is stored. Thus, we cannot display
2277 accurate messages if the function or data definition spans multiple
2280 /* save current parse state in 's' */
2281 void save_parse_state(ParseState
*s
)
2283 s
->line_num
= file
->line_num
;
2284 s
->macro_ptr
= macro_ptr
;
2289 /* restore parse state from 's' */
2290 void restore_parse_state(ParseState
*s
)
2292 file
->line_num
= s
->line_num
;
2293 macro_ptr
= s
->macro_ptr
;
2298 /* return the number of additional 'ints' necessary to store the
2300 static inline int tok_ext_size(int t
)
2314 error("unsupported token");
2321 return LDOUBLE_SIZE
/ 4;
2327 /* token string handling */
2329 static inline void tok_str_new(TokenString
*s
)
2333 s
->allocated_len
= 0;
2334 s
->last_line_num
= -1;
2337 static void tok_str_free(int *str
)
2342 static int *tok_str_realloc(TokenString
*s
)
2346 if (s
->allocated_len
== 0) {
2349 len
= s
->allocated_len
* 2;
2351 str
= tcc_realloc(s
->str
, len
* sizeof(int));
2353 error("memory full");
2354 s
->allocated_len
= len
;
2359 static void tok_str_add(TokenString
*s
, int t
)
2365 if (len
>= s
->allocated_len
)
2366 str
= tok_str_realloc(s
);
2371 static void tok_str_add2(TokenString
*s
, int t
, CValue
*cv
)
2378 /* allocate space for worst case */
2379 if (len
+ TOK_MAX_SIZE
> s
->allocated_len
)
2380 str
= tok_str_realloc(s
);
2389 str
[len
++] = cv
->tab
[0];
2398 nb_words
= (sizeof(CString
) + cv
->cstr
->size
+ 3) >> 2;
2399 while ((len
+ nb_words
) > s
->allocated_len
)
2400 str
= tok_str_realloc(s
);
2401 cstr
= (CString
*)(str
+ len
);
2403 cstr
->size
= cv
->cstr
->size
;
2404 cstr
->data_allocated
= NULL
;
2405 cstr
->size_allocated
= cstr
->size
;
2406 memcpy((char *)cstr
+ sizeof(CString
),
2407 cv
->cstr
->data
, cstr
->size
);
2414 #if LDOUBLE_SIZE == 8
2417 str
[len
++] = cv
->tab
[0];
2418 str
[len
++] = cv
->tab
[1];
2420 #if LDOUBLE_SIZE == 12
2422 str
[len
++] = cv
->tab
[0];
2423 str
[len
++] = cv
->tab
[1];
2424 str
[len
++] = cv
->tab
[2];
2425 #elif LDOUBLE_SIZE != 8
2426 #error add long double size support
2435 /* add the current parse token in token string 's' */
2436 static void tok_str_add_tok(TokenString
*s
)
2440 /* save line number info */
2441 if (file
->line_num
!= s
->last_line_num
) {
2442 s
->last_line_num
= file
->line_num
;
2443 cval
.i
= s
->last_line_num
;
2444 tok_str_add2(s
, TOK_LINENUM
, &cval
);
2446 tok_str_add2(s
, tok
, &tokc
);
2449 #if LDOUBLE_SIZE == 12
2450 #define LDOUBLE_GET(p, cv) \
2454 #elif LDOUBLE_SIZE == 8
2455 #define LDOUBLE_GET(p, cv) \
2459 #error add long double size support
2463 /* get a token from an integer array and increment pointer
2464 accordingly. we code it as a macro to avoid pointer aliasing. */
2465 #define TOK_GET(t, p, cv) \
2480 cv.cstr = (CString *)p; \
2481 cv.cstr->data = (char *)p + sizeof(CString);\
2482 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2491 case TOK_CLDOUBLE: \
2492 LDOUBLE_GET(p, cv); \
2493 p += LDOUBLE_SIZE / 4; \
2500 /* defines handling */
2501 static inline void define_push(int v
, int macro_type
, int *str
, Sym
*first_arg
)
2505 s
= sym_push2(&define_stack
, v
, macro_type
, (int)str
);
2506 s
->next
= first_arg
;
2507 table_ident
[v
- TOK_IDENT
]->sym_define
= s
;
2510 /* undefined a define symbol. Its name is just set to zero */
2511 static void define_undef(Sym
*s
)
2515 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2516 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2520 static inline Sym
*define_find(int v
)
2523 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2525 return table_ident
[v
]->sym_define
;
2528 /* free define stack until top reaches 'b' */
2529 static void free_defines(Sym
*b
)
2537 /* do not free args or predefined defines */
2539 tok_str_free((int *)top
->c
);
2541 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2542 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2550 static Sym
*label_find(int v
)
2553 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2555 return table_ident
[v
]->sym_label
;
2558 static Sym
*label_push(Sym
**ptop
, int v
, int flags
)
2561 s
= sym_push2(ptop
, v
, 0, 0);
2563 ps
= &table_ident
[v
- TOK_IDENT
]->sym_label
;
2564 if (ptop
== &global_label_stack
) {
2565 /* modify the top most local identifier, so that
2566 sym_identifier will point to 's' when popped */
2568 ps
= &(*ps
)->prev_tok
;
2575 /* pop labels until element last is reached. Look if any labels are
2576 undefined. Define symbols if '&&label' was used. */
2577 static void label_pop(Sym
**ptop
, Sym
*slast
)
2580 for(s
= *ptop
; s
!= slast
; s
= s1
) {
2582 if (s
->r
== LABEL_DECLARED
) {
2583 warning("label '%s' declared but not used", get_tok_str(s
->v
, NULL
));
2584 } else if (s
->r
== LABEL_FORWARD
) {
2585 error("label '%s' used but not defined",
2586 get_tok_str(s
->v
, NULL
));
2589 /* define corresponding symbol. A size of
2591 put_extern_sym(s
, cur_text_section
, (long)s
->next
, 1);
2595 table_ident
[s
->v
- TOK_IDENT
]->sym_label
= s
->prev_tok
;
2601 /* eval an expression for #if/#elif */
2602 static int expr_preprocess(void)
2608 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2609 next(); /* do macro subst */
2610 if (tok
== TOK_DEFINED
) {
2615 c
= define_find(tok
) != 0;
2620 } else if (tok
>= TOK_IDENT
) {
2621 /* if undefined macro */
2625 tok_str_add_tok(&str
);
2627 tok_str_add(&str
, -1); /* simulate end of file */
2628 tok_str_add(&str
, 0);
2629 /* now evaluate C constant expression */
2630 macro_ptr
= str
.str
;
2634 tok_str_free(str
.str
);
2638 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2639 static void tok_print(int *str
)
2645 TOK_GET(t
, str
, cval
);
2648 printf(" %s", get_tok_str(t
, &cval
));
2654 /* parse after #define */
2655 static void parse_define(void)
2657 Sym
*s
, *first
, **ps
;
2658 int v
, t
, varg
, is_vaargs
, c
;
2663 error("invalid macro name '%s'", get_tok_str(tok
, &tokc
));
2664 /* XXX: should check if same macro (ANSI) */
2667 /* '(' must be just after macro definition for MACRO_FUNC */
2668 c
= file
->buf_ptr
[0];
2670 c
= handle_stray1(file
->buf_ptr
);
2675 while (tok
!= ')') {
2679 if (varg
== TOK_DOTS
) {
2680 varg
= TOK___VA_ARGS__
;
2682 } else if (tok
== TOK_DOTS
&& gnu_ext
) {
2686 if (varg
< TOK_IDENT
)
2687 error("badly punctuated parameter list");
2688 s
= sym_push2(&define_stack
, varg
| SYM_FIELD
, is_vaargs
, 0);
2699 /* EOF testing necessary for '-D' handling */
2700 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2701 tok_str_add2(&str
, tok
, &tokc
);
2704 tok_str_add(&str
, 0);
2706 printf("define %s %d: ", get_tok_str(v
, NULL
), t
);
2709 define_push(v
, t
, str
.str
, first
);
2712 static inline int hash_cached_include(int type
, const char *filename
)
2714 const unsigned char *s
;
2718 h
= TOK_HASH_FUNC(h
, type
);
2721 h
= TOK_HASH_FUNC(h
, *s
);
2724 h
&= (CACHED_INCLUDES_HASH_SIZE
- 1);
2728 /* XXX: use a token or a hash table to accelerate matching ? */
2729 static CachedInclude
*search_cached_include(TCCState
*s1
,
2730 int type
, const char *filename
)
2734 h
= hash_cached_include(type
, filename
);
2735 i
= s1
->cached_includes_hash
[h
];
2739 e
= s1
->cached_includes
[i
- 1];
2740 if (e
->type
== type
&& !strcmp(e
->filename
, filename
))
2747 static inline void add_cached_include(TCCState
*s1
, int type
,
2748 const char *filename
, int ifndef_macro
)
2753 if (search_cached_include(s1
, type
, filename
))
2756 printf("adding cached '%s' %s\n", filename
, get_tok_str(ifndef_macro
, NULL
));
2758 e
= tcc_malloc(sizeof(CachedInclude
) + strlen(filename
));
2762 strcpy(e
->filename
, filename
);
2763 e
->ifndef_macro
= ifndef_macro
;
2764 dynarray_add((void ***)&s1
->cached_includes
, &s1
->nb_cached_includes
, e
);
2765 /* add in hash table */
2766 h
= hash_cached_include(type
, filename
);
2767 e
->hash_next
= s1
->cached_includes_hash
[h
];
2768 s1
->cached_includes_hash
[h
] = s1
->nb_cached_includes
;
2771 static void pragma_parse(TCCState
*s1
)
2776 if (tok
== TOK_pack
) {
2779 #pragma pack(1) // set
2780 #pragma pack() // reset to default
2781 #pragma pack(push,1) // push & set
2782 #pragma pack(pop) // restore previous
2786 if (tok
== TOK_ASM_pop
) {
2788 if (s1
->pack_stack_ptr
<= s1
->pack_stack
) {
2790 error("out of pack stack");
2792 s1
->pack_stack_ptr
--;
2796 if (tok
== TOK_ASM_push
) {
2798 if (s1
->pack_stack_ptr
>= s1
->pack_stack
+ PACK_STACK_SIZE
- 1)
2800 s1
->pack_stack_ptr
++;
2803 if (tok
!= TOK_CINT
) {
2805 error("invalid pack pragma");
2808 if (val
< 1 || val
> 16 || (val
& (val
- 1)) != 0)
2812 *s1
->pack_stack_ptr
= val
;
2818 /* is_bof is true if first non space token at beginning of file */
2819 static void preprocess(int is_bof
)
2821 TCCState
*s1
= tcc_state
;
2822 int size
, i
, c
, n
, saved_parse_flags
;
2823 char buf
[1024], *q
, *p
;
2829 saved_parse_flags
= parse_flags
;
2830 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
|
2831 PARSE_FLAG_LINEFEED
;
2841 s
= define_find(tok
);
2842 /* undefine symbol by putting an invalid name */
2847 case TOK_INCLUDE_NEXT
:
2848 ch
= file
->buf_ptr
[0];
2849 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2854 } else if (ch
== '\"') {
2857 /* XXX: better stray handling */
2860 while (ch
!= c
&& ch
!= '\n' && ch
!= CH_EOF
) {
2861 if ((q
- buf
) < sizeof(buf
) - 1)
2868 /* eat all spaces and comments after include */
2869 /* XXX: slightly incorrect */
2870 while (ch1
!= '\n' && ch1
!= CH_EOF
)
2874 /* computed #include : either we have only strings or
2875 we have anything enclosed in '<>' */
2878 if (tok
== TOK_STR
) {
2879 while (tok
!= TOK_LINEFEED
) {
2880 if (tok
!= TOK_STR
) {
2882 error("'#include' expects \"FILENAME\" or <FILENAME>");
2884 pstrcat(buf
, sizeof(buf
), (char *)tokc
.cstr
->data
);
2890 while (tok
!= TOK_LINEFEED
) {
2891 pstrcat(buf
, sizeof(buf
), get_tok_str(tok
, &tokc
));
2895 /* check syntax and remove '<>' */
2896 if (len
< 2 || buf
[0] != '<' || buf
[len
- 1] != '>')
2897 goto include_syntax
;
2898 memmove(buf
, buf
+ 1, len
- 2);
2899 buf
[len
- 2] = '\0';
2904 e
= search_cached_include(s1
, c
, buf
);
2905 if (e
&& define_find(e
->ifndef_macro
)) {
2906 /* no need to parse the include because the 'ifndef macro'
2909 printf("%s: skipping %s\n", file
->filename
, buf
);
2913 /* first search in current dir if "header.h" */
2915 p
= strrchr(file
->filename
, '/');
2917 size
= p
+ 1 - file
->filename
;
2918 if (size
> sizeof(buf1
) - 1)
2919 size
= sizeof(buf1
) - 1;
2920 memcpy(buf1
, file
->filename
, size
);
2922 pstrcat(buf1
, sizeof(buf1
), buf
);
2923 f
= tcc_open(s1
, buf1
);
2925 if (tok
== TOK_INCLUDE_NEXT
)
2931 if (s1
->include_stack_ptr
>= s1
->include_stack
+ INCLUDE_STACK_SIZE
)
2932 error("#include recursion too deep");
2933 /* now search in all the include paths */
2934 n
= s1
->nb_include_paths
+ s1
->nb_sysinclude_paths
;
2935 for(i
= 0; i
< n
; i
++) {
2937 if (i
< s1
->nb_include_paths
)
2938 path
= s1
->include_paths
[i
];
2940 path
= s1
->sysinclude_paths
[i
- s1
->nb_include_paths
];
2941 pstrcpy(buf1
, sizeof(buf1
), path
);
2942 pstrcat(buf1
, sizeof(buf1
), "/");
2943 pstrcat(buf1
, sizeof(buf1
), buf
);
2944 f
= tcc_open(s1
, buf1
);
2946 if (tok
== TOK_INCLUDE_NEXT
)
2952 error("include file '%s' not found", buf
);
2956 printf("%s: including %s\n", file
->filename
, buf1
);
2959 pstrcpy(f
->inc_filename
, sizeof(f
->inc_filename
), buf
);
2960 /* push current file in stack */
2961 /* XXX: fix current line init */
2962 *s1
->include_stack_ptr
++ = file
;
2964 /* add include file debug info */
2966 put_stabs(file
->filename
, N_BINCL
, 0, 0, 0);
2968 tok_flags
|= TOK_FLAG_BOF
| TOK_FLAG_BOL
;
2969 ch
= file
->buf_ptr
[0];
2977 c
= expr_preprocess();
2983 if (tok
< TOK_IDENT
)
2984 error("invalid argument for '#if%sdef'", c
? "n" : "");
2988 printf("#ifndef %s\n", get_tok_str(tok
, NULL
));
2990 file
->ifndef_macro
= tok
;
2993 c
= (define_find(tok
) != 0) ^ c
;
2995 if (s1
->ifdef_stack_ptr
>= s1
->ifdef_stack
+ IFDEF_STACK_SIZE
)
2996 error("memory full");
2997 *s1
->ifdef_stack_ptr
++ = c
;
3000 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
3001 error("#else without matching #if");
3002 if (s1
->ifdef_stack_ptr
[-1] & 2)
3003 error("#else after #else");
3004 c
= (s1
->ifdef_stack_ptr
[-1] ^= 3);
3007 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
3008 error("#elif without matching #if");
3009 c
= s1
->ifdef_stack_ptr
[-1];
3011 error("#elif after #else");
3012 /* last #if/#elif expression was true: we skip */
3015 c
= expr_preprocess();
3016 s1
->ifdef_stack_ptr
[-1] = c
;
3026 if (s1
->ifdef_stack_ptr
<= file
->ifdef_stack_ptr
)
3027 error("#endif without matching #if");
3028 s1
->ifdef_stack_ptr
--;
3029 /* '#ifndef macro' was at the start of file. Now we check if
3030 an '#endif' is exactly at the end of file */
3031 if (file
->ifndef_macro
&&
3032 s1
->ifdef_stack_ptr
== file
->ifdef_stack_ptr
) {
3033 file
->ifndef_macro_saved
= file
->ifndef_macro
;
3034 /* need to set to zero to avoid false matches if another
3035 #ifndef at middle of file */
3036 file
->ifndef_macro
= 0;
3037 while (tok
!= TOK_LINEFEED
)
3039 tok_flags
|= TOK_FLAG_ENDIF
;
3045 if (tok
!= TOK_CINT
)
3047 file
->line_num
= tokc
.i
- 1; /* the line number will be incremented after */
3049 if (tok
!= TOK_LINEFEED
) {
3052 pstrcpy(file
->filename
, sizeof(file
->filename
),
3053 (char *)tokc
.cstr
->data
);
3059 ch
= file
->buf_ptr
[0];
3062 while (ch
!= '\n' && ch
!= CH_EOF
) {
3063 if ((q
- buf
) < sizeof(buf
) - 1)
3069 error("#error %s", buf
);
3071 warning("#warning %s", buf
);
3077 if (tok
== TOK_LINEFEED
|| tok
== '!' || tok
== TOK_CINT
) {
3078 /* '!' is ignored to allow C scripts. numbers are ignored
3079 to emulate cpp behaviour */
3081 if (!(saved_parse_flags
& PARSE_FLAG_ASM_COMMENTS
))
3082 error("invalid preprocessing directive #%s", get_tok_str(tok
, &tokc
));
3086 /* ignore other preprocess commands or #! for C scripts */
3087 while (tok
!= TOK_LINEFEED
)
3090 parse_flags
= saved_parse_flags
;
3093 /* evaluate escape codes in a string. */
3094 static void parse_escape_string(CString
*outstr
, const uint8_t *buf
, int is_long
)
3109 case '0': case '1': case '2': case '3':
3110 case '4': case '5': case '6': case '7':
3111 /* at most three octal digits */
3116 n
= n
* 8 + c
- '0';
3120 n
= n
* 8 + c
- '0';
3125 goto add_char_nonext
;
3133 if (c
>= 'a' && c
<= 'f')
3135 else if (c
>= 'A' && c
<= 'F')
3145 goto add_char_nonext
;
3169 goto invalid_escape
;
3179 if (c
>= '!' && c
<= '~')
3180 warning("unknown escape sequence: \'\\%c\'", c
);
3182 warning("unknown escape sequence: \'\\x%x\'", c
);
3189 cstr_ccat(outstr
, c
);
3191 cstr_wccat(outstr
, c
);
3193 /* add a trailing '\0' */
3195 cstr_ccat(outstr
, '\0');
3197 cstr_wccat(outstr
, '\0');
3200 /* we use 64 bit numbers */
3203 /* bn = (bn << shift) | or_val */
3204 void bn_lshift(unsigned int *bn
, int shift
, int or_val
)
3208 for(i
=0;i
<BN_SIZE
;i
++) {
3210 bn
[i
] = (v
<< shift
) | or_val
;
3211 or_val
= v
>> (32 - shift
);
3215 void bn_zero(unsigned int *bn
)
3218 for(i
=0;i
<BN_SIZE
;i
++) {
3223 /* parse number in null terminated string 'p' and return it in the
3225 void parse_number(const char *p
)
3227 int b
, t
, shift
, frac_bits
, s
, exp_val
, ch
;
3229 unsigned int bn
[BN_SIZE
];
3240 goto float_frac_parse
;
3241 } else if (t
== '0') {
3242 if (ch
== 'x' || ch
== 'X') {
3246 } else if (tcc_ext
&& (ch
== 'b' || ch
== 'B')) {
3252 /* parse all digits. cannot check octal numbers at this stage
3253 because of floating point constants */
3255 if (ch
>= 'a' && ch
<= 'f')
3257 else if (ch
>= 'A' && ch
<= 'F')
3265 if (q
>= token_buf
+ STRING_MAX_SIZE
) {
3267 error("number too long");
3273 ((ch
== 'e' || ch
== 'E') && b
== 10) ||
3274 ((ch
== 'p' || ch
== 'P') && (b
== 16 || b
== 2))) {
3276 /* NOTE: strtox should support that for hexa numbers, but
3277 non ISOC99 libcs do not support it, so we prefer to do
3279 /* hexadecimal or binary floats */
3280 /* XXX: handle overflows */
3292 } else if (t
>= 'a') {
3294 } else if (t
>= 'A') {
3299 bn_lshift(bn
, shift
, t
);
3306 if (t
>= 'a' && t
<= 'f') {
3308 } else if (t
>= 'A' && t
<= 'F') {
3310 } else if (t
>= '0' && t
<= '9') {
3316 error("invalid digit");
3317 bn_lshift(bn
, shift
, t
);
3322 if (ch
!= 'p' && ch
!= 'P')
3329 } else if (ch
== '-') {
3333 if (ch
< '0' || ch
> '9')
3334 expect("exponent digits");
3335 while (ch
>= '0' && ch
<= '9') {
3336 exp_val
= exp_val
* 10 + ch
- '0';
3339 exp_val
= exp_val
* s
;
3341 /* now we can generate the number */
3342 /* XXX: should patch directly float number */
3343 d
= (double)bn
[1] * 4294967296.0 + (double)bn
[0];
3344 d
= ldexp(d
, exp_val
- frac_bits
);
3349 /* float : should handle overflow */
3351 } else if (t
== 'L') {
3354 /* XXX: not large enough */
3355 tokc
.ld
= (long double)d
;
3361 /* decimal floats */
3363 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3368 while (ch
>= '0' && ch
<= '9') {
3369 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3375 if (ch
== 'e' || ch
== 'E') {
3376 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3380 if (ch
== '-' || ch
== '+') {
3381 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3386 if (ch
< '0' || ch
> '9')
3387 expect("exponent digits");
3388 while (ch
>= '0' && ch
<= '9') {
3389 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3401 tokc
.f
= strtof(token_buf
, NULL
);
3402 } else if (t
== 'L') {
3405 tokc
.ld
= strtold(token_buf
, NULL
);
3408 tokc
.d
= strtod(token_buf
, NULL
);
3412 unsigned long long n
, n1
;
3415 /* integer number */
3418 if (b
== 10 && *q
== '0') {
3425 /* no need for checks except for base 10 / 8 errors */
3428 } else if (t
>= 'a') {
3430 } else if (t
>= 'A') {
3435 error("invalid digit");
3439 /* detect overflow */
3440 /* XXX: this test is not reliable */
3442 error("integer constant overflow");
3445 /* XXX: not exactly ANSI compliant */
3446 if ((n
& 0xffffffff00000000LL
) != 0) {
3451 } else if (n
> 0x7fffffff) {
3462 error("three 'l's in integer constant");
3465 if (tok
== TOK_CINT
)
3467 else if (tok
== TOK_CUINT
)
3471 } else if (t
== 'U') {
3473 error("two 'u's in integer constant");
3475 if (tok
== TOK_CINT
)
3477 else if (tok
== TOK_CLLONG
)
3484 if (tok
== TOK_CINT
|| tok
== TOK_CUINT
)
3492 #define PARSE2(c1, tok1, c2, tok2) \
3503 /* return next token without macro substitution */
3504 static inline void next_nomacro1(void)
3524 /* first look if it is in fact an end of buffer */
3525 if (p
>= file
->buf_end
) {
3529 if (p
>= file
->buf_end
)
3542 TCCState
*s1
= tcc_state
;
3543 if (parse_flags
& PARSE_FLAG_LINEFEED
) {
3545 } else if (s1
->include_stack_ptr
== s1
->include_stack
||
3546 !(parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3547 /* no include left : end of file. */
3550 /* pop include file */
3552 /* test if previous '#endif' was after a #ifdef at
3554 if (tok_flags
& TOK_FLAG_ENDIF
) {
3556 printf("#endif %s\n", get_tok_str(file
->ifndef_macro_saved
, NULL
));
3558 add_cached_include(s1
, file
->inc_type
, file
->inc_filename
,
3559 file
->ifndef_macro_saved
);
3562 /* add end of include file debug info */
3564 put_stabd(N_EINCL
, 0, 0);
3566 /* pop include stack */
3568 s1
->include_stack_ptr
--;
3569 file
= *s1
->include_stack_ptr
;
3577 if (parse_flags
& PARSE_FLAG_LINEFEED
) {
3581 tok_flags
|= TOK_FLAG_BOL
;
3590 if ((tok_flags
& TOK_FLAG_BOL
) &&
3591 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3593 preprocess(tok_flags
& TOK_FLAG_BOF
);
3599 tok
= TOK_TWOSHARPS
;
3601 if (parse_flags
& PARSE_FLAG_ASM_COMMENTS
) {
3602 p
= parse_line_comment(p
- 1);
3611 case 'a': case 'b': case 'c': case 'd':
3612 case 'e': case 'f': case 'g': case 'h':
3613 case 'i': case 'j': case 'k': case 'l':
3614 case 'm': case 'n': case 'o': case 'p':
3615 case 'q': case 'r': case 's': case 't':
3616 case 'u': case 'v': case 'w': case 'x':
3618 case 'A': case 'B': case 'C': case 'D':
3619 case 'E': case 'F': case 'G': case 'H':
3620 case 'I': case 'J': case 'K':
3621 case 'M': case 'N': case 'O': case 'P':
3622 case 'Q': case 'R': case 'S': case 'T':
3623 case 'U': case 'V': case 'W': case 'X':
3629 h
= TOK_HASH_FUNC(h
, c
);
3633 if (!isidnum_table
[c
])
3635 h
= TOK_HASH_FUNC(h
, c
);
3642 /* fast case : no stray found, so we have the full token
3643 and we have already hashed it */
3645 h
&= (TOK_HASH_SIZE
- 1);
3646 pts
= &hash_ident
[h
];
3651 if (ts
->len
== len
&& !memcmp(ts
->str
, p1
, len
))
3653 pts
= &(ts
->hash_next
);
3655 ts
= tok_alloc_new(pts
, p1
, len
);
3659 cstr_reset(&tokcstr
);
3662 cstr_ccat(&tokcstr
, *p1
);
3668 while (isidnum_table
[c
]) {
3669 cstr_ccat(&tokcstr
, c
);
3672 ts
= tok_alloc(tokcstr
.data
, tokcstr
.size
);
3678 if (t
!= '\\' && t
!= '\'' && t
!= '\"') {
3680 goto parse_ident_fast
;
3683 if (c
== '\'' || c
== '\"') {
3687 cstr_reset(&tokcstr
);
3688 cstr_ccat(&tokcstr
, 'L');
3689 goto parse_ident_slow
;
3693 case '0': case '1': case '2': case '3':
3694 case '4': case '5': case '6': case '7':
3697 cstr_reset(&tokcstr
);
3698 /* after the first digit, accept digits, alpha, '.' or sign if
3699 prefixed by 'eEpP' */
3703 cstr_ccat(&tokcstr
, c
);
3705 if (!(isnum(c
) || isid(c
) || c
== '.' ||
3706 ((c
== '+' || c
== '-') &&
3707 (t
== 'e' || t
== 'E' || t
== 'p' || t
== 'P'))))
3710 /* We add a trailing '\0' to ease parsing */
3711 cstr_ccat(&tokcstr
, '\0');
3712 tokc
.cstr
= &tokcstr
;
3716 /* special dot handling because it can also start a number */
3719 cstr_reset(&tokcstr
);
3720 cstr_ccat(&tokcstr
, '.');
3722 } else if (c
== '.') {
3742 /* parse the string */
3744 p
= parse_pp_string(p
, sep
, &str
);
3745 cstr_ccat(&str
, '\0');
3747 /* eval the escape (should be done as TOK_PPNUM) */
3748 cstr_reset(&tokcstr
);
3749 parse_escape_string(&tokcstr
, str
.data
, is_long
);
3754 /* XXX: make it portable */
3758 char_size
= sizeof(nwchar_t
);
3759 if (tokcstr
.size
<= char_size
)
3760 error("empty character constant");
3761 if (tokcstr
.size
> 2 * char_size
)
3762 warning("multi-character character constant");
3764 tokc
.i
= *(int8_t *)tokcstr
.data
;
3767 tokc
.i
= *(nwchar_t
*)tokcstr
.data
;
3771 tokc
.cstr
= &tokcstr
;
3785 } else if (c
== '<') {
3803 } else if (c
== '>') {
3821 } else if (c
== '=') {
3834 } else if (c
== '=') {
3847 } else if (c
== '=') {
3860 } else if (c
== '=') {
3863 } else if (c
== '>') {
3871 PARSE2('!', '!', '=', TOK_NE
)
3872 PARSE2('=', '=', '=', TOK_EQ
)
3873 PARSE2('*', '*', '=', TOK_A_MUL
)
3874 PARSE2('%', '%', '=', TOK_A_MOD
)
3875 PARSE2('^', '^', '=', TOK_A_XOR
)
3877 /* comments or operator */
3881 p
= parse_comment(p
);
3883 } else if (c
== '/') {
3884 p
= parse_line_comment(p
);
3886 } else if (c
== '=') {
3906 case '$': /* only used in assembler */
3907 case '@': /* dito */
3912 error("unrecognized character \\x%02x", c
);
3917 #if defined(PARSE_DEBUG)
3918 printf("token = %s\n", get_tok_str(tok
, &tokc
));
3922 /* return next token without macro substitution. Can read input from
3924 static void next_nomacro(void)
3930 TOK_GET(tok
, macro_ptr
, tokc
);
3931 if (tok
== TOK_LINENUM
) {
3932 file
->line_num
= tokc
.i
;
3941 /* substitute args in macro_str and return allocated string */
3942 static int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
3944 int *st
, last_tok
, t
, notfirst
;
3953 TOK_GET(t
, macro_str
, cval
);
3958 TOK_GET(t
, macro_str
, cval
);
3961 s
= sym_find2(args
, t
);
3968 cstr_ccat(&cstr
, ' ');
3969 TOK_GET(t
, st
, cval
);
3970 cstr_cat(&cstr
, get_tok_str(t
, &cval
));
3973 cstr_ccat(&cstr
, '\0');
3975 printf("stringize: %s\n", (char *)cstr
.data
);
3979 tok_str_add2(&str
, TOK_STR
, &cval
);
3982 tok_str_add2(&str
, t
, &cval
);
3984 } else if (t
>= TOK_IDENT
) {
3985 s
= sym_find2(args
, t
);
3988 /* if '##' is present before or after, no arg substitution */
3989 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
3990 /* special case for var arg macros : ## eats the
3991 ',' if empty VA_ARGS variable. */
3992 /* XXX: test of the ',' is not 100%
3993 reliable. should fix it to avoid security
3995 if (gnu_ext
&& s
->type
.t
&&
3996 last_tok
== TOK_TWOSHARPS
&&
3997 str
.len
>= 2 && str
.str
[str
.len
- 2] == ',') {
3999 /* suppress ',' '##' */
4002 /* suppress '##' and add variable */
4010 TOK_GET(t1
, st
, cval
);
4013 tok_str_add2(&str
, t1
, &cval
);
4017 /* NOTE: the stream cannot be read when macro
4018 substituing an argument */
4019 macro_subst(&str
, nested_list
, st
, NULL
);
4022 tok_str_add(&str
, t
);
4025 tok_str_add2(&str
, t
, &cval
);
4029 tok_str_add(&str
, 0);
4033 static char const ab_month_name
[12][4] =
4035 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4036 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4039 /* do macro substitution of current token with macro 's' and add
4040 result to (tok_str,tok_len). 'nested_list' is the list of all
4041 macros we got inside to avoid recursing. Return non zero if no
4042 substitution needs to be done */
4043 static int macro_subst_tok(TokenString
*tok_str
,
4044 Sym
**nested_list
, Sym
*s
, struct macro_level
**can_read_stream
)
4046 Sym
*args
, *sa
, *sa1
;
4047 int mstr_allocated
, parlevel
, *mstr
, t
, t1
;
4054 /* if symbol is a macro, prepare substitution */
4055 /* special macros */
4056 if (tok
== TOK___LINE__
) {
4057 snprintf(buf
, sizeof(buf
), "%d", file
->line_num
);
4061 } else if (tok
== TOK___FILE__
) {
4062 cstrval
= file
->filename
;
4064 } else if (tok
== TOK___DATE__
|| tok
== TOK___TIME__
) {
4069 tm
= localtime(&ti
);
4070 if (tok
== TOK___DATE__
) {
4071 snprintf(buf
, sizeof(buf
), "%s %2d %d",
4072 ab_month_name
[tm
->tm_mon
], tm
->tm_mday
, tm
->tm_year
+ 1900);
4074 snprintf(buf
, sizeof(buf
), "%02d:%02d:%02d",
4075 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
);
4082 cstr_cat(&cstr
, cstrval
);
4083 cstr_ccat(&cstr
, '\0');
4085 tok_str_add2(tok_str
, t1
, &cval
);
4090 if (s
->type
.t
== MACRO_FUNC
) {
4091 /* NOTE: we do not use next_nomacro to avoid eating the
4092 next token. XXX: find better solution */
4096 if (t
== 0 && can_read_stream
) {
4097 /* end of macro stream: we must look at the token
4098 after in the file */
4099 struct macro_level
*ml
= *can_read_stream
;
4105 *can_read_stream
= ml
-> prev
;
4110 /* XXX: incorrect with comments */
4111 ch
= file
->buf_ptr
[0];
4112 while (is_space(ch
) || ch
== '\n')
4116 if (t
!= '(') /* no macro subst */
4119 /* argument macro */
4124 /* NOTE: empty args are allowed, except if no args */
4126 /* handle '()' case */
4127 if (!args
&& !sa
&& tok
== ')')
4130 error("macro '%s' used with too many args",
4131 get_tok_str(s
->v
, 0));
4134 /* NOTE: non zero sa->t indicates VA_ARGS */
4135 while ((parlevel
> 0 ||
4137 (tok
!= ',' || sa
->type
.t
))) &&
4141 else if (tok
== ')')
4143 tok_str_add2(&str
, tok
, &tokc
);
4146 tok_str_add(&str
, 0);
4147 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, sa
->type
.t
, (int)str
.str
);
4150 /* special case for gcc var args: add an empty
4151 var arg argument if it is omitted */
4152 if (sa
&& sa
->type
.t
&& gnu_ext
)
4162 error("macro '%s' used with too few args",
4163 get_tok_str(s
->v
, 0));
4166 /* now subst each arg */
4167 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
4172 tok_str_free((int *)sa
->c
);
4178 sym_push2(nested_list
, s
->v
, 0, 0);
4179 macro_subst(tok_str
, nested_list
, mstr
, can_read_stream
);
4180 /* pop nested defined symbol */
4182 *nested_list
= sa1
->prev
;
4190 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4191 return the resulting string (which must be freed). */
4192 static inline int *macro_twosharps(const int *macro_str
)
4195 const int *macro_ptr1
, *start_macro_ptr
, *ptr
, *saved_macro_ptr
;
4197 const char *p1
, *p2
;
4199 TokenString macro_str1
;
4202 start_macro_ptr
= macro_str
;
4203 /* we search the first '##' */
4205 macro_ptr1
= macro_str
;
4206 TOK_GET(t
, macro_str
, cval
);
4207 /* nothing more to do if end of string */
4210 if (*macro_str
== TOK_TWOSHARPS
)
4214 /* we saw '##', so we need more processing to handle it */
4216 tok_str_new(¯o_str1
);
4220 /* add all tokens seen so far */
4221 for(ptr
= start_macro_ptr
; ptr
< macro_ptr1
;) {
4222 TOK_GET(t
, ptr
, cval
);
4223 tok_str_add2(¯o_str1
, t
, &cval
);
4225 saved_macro_ptr
= macro_ptr
;
4226 /* XXX: get rid of the use of macro_ptr here */
4227 macro_ptr
= (int *)macro_str
;
4229 while (*macro_ptr
== TOK_TWOSHARPS
) {
4231 macro_ptr1
= macro_ptr
;
4234 TOK_GET(t
, macro_ptr
, cval
);
4235 /* We concatenate the two tokens if we have an
4236 identifier or a preprocessing number */
4238 p1
= get_tok_str(tok
, &tokc
);
4239 cstr_cat(&cstr
, p1
);
4240 p2
= get_tok_str(t
, &cval
);
4241 cstr_cat(&cstr
, p2
);
4242 cstr_ccat(&cstr
, '\0');
4244 if ((tok
>= TOK_IDENT
|| tok
== TOK_PPNUM
) &&
4245 (t
>= TOK_IDENT
|| t
== TOK_PPNUM
)) {
4246 if (tok
== TOK_PPNUM
) {
4247 /* if number, then create a number token */
4248 /* NOTE: no need to allocate because
4249 tok_str_add2() does it */
4250 cstr_reset(&tokcstr
);
4253 tokc
.cstr
= &tokcstr
;
4255 /* if identifier, we must do a test to
4256 validate we have a correct identifier */
4257 if (t
== TOK_PPNUM
) {
4267 if (!isnum(c
) && !isid(c
))
4271 ts
= tok_alloc(cstr
.data
, strlen(cstr
.data
));
4272 tok
= ts
->tok
; /* modify current token */
4275 const char *str
= cstr
.data
;
4276 const unsigned char *q
;
4278 /* we look for a valid token */
4279 /* XXX: do more extensive checks */
4280 if (!strcmp(str
, ">>=")) {
4282 } else if (!strcmp(str
, "<<=")) {
4284 } else if (strlen(str
) == 2) {
4285 /* search in two bytes table */
4290 if (q
[0] == str
[0] && q
[1] == str
[1])
4297 /* NOTE: because get_tok_str use a static buffer,
4300 p1
= get_tok_str(tok
, &tokc
);
4301 cstr_cat(&cstr
, p1
);
4302 cstr_ccat(&cstr
, '\0');
4303 p2
= get_tok_str(t
, &cval
);
4304 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr
.data
, p2
);
4305 /* cannot merge tokens: just add them separately */
4306 tok_str_add2(¯o_str1
, tok
, &tokc
);
4307 /* XXX: free associated memory ? */
4314 tok_str_add2(¯o_str1
, tok
, &tokc
);
4319 macro_ptr
= (int *)saved_macro_ptr
;
4321 tok_str_add(¯o_str1
, 0);
4322 return macro_str1
.str
;
4326 /* do macro substitution of macro_str and add result to
4327 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4328 inside to avoid recursing. */
4329 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
4330 const int *macro_str
, struct macro_level
** can_read_stream
)
4337 struct macro_level ml
;
4339 /* first scan for '##' operator handling */
4341 macro_str1
= macro_twosharps(ptr
);
4345 /* NOTE: ptr == NULL can only happen if tokens are read from
4346 file stream due to a macro function call */
4349 TOK_GET(t
, ptr
, cval
);
4354 /* if nested substitution, do nothing */
4355 if (sym_find2(*nested_list
, t
))
4358 if (can_read_stream
)
4359 ml
.prev
= *can_read_stream
, *can_read_stream
= &ml
;
4360 macro_ptr
= (int *)ptr
;
4362 ret
= macro_subst_tok(tok_str
, nested_list
, s
, can_read_stream
);
4363 ptr
= (int *)macro_ptr
;
4365 if (can_read_stream
&& *can_read_stream
== &ml
)
4366 *can_read_stream
= ml
.prev
;
4371 tok_str_add2(tok_str
, t
, &cval
);
4375 tok_str_free(macro_str1
);
4378 /* return next token with macro substitution */
4379 static void next(void)
4381 Sym
*nested_list
, *s
;
4383 struct macro_level
*ml
;
4388 /* if not reading from macro substituted string, then try
4389 to substitute macros */
4390 if (tok
>= TOK_IDENT
&&
4391 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
4392 s
= define_find(tok
);
4394 /* we have a macro: we try to substitute */
4398 if (macro_subst_tok(&str
, &nested_list
, s
, &ml
) == 0) {
4399 /* substitution done, NOTE: maybe empty */
4400 tok_str_add(&str
, 0);
4401 macro_ptr
= str
.str
;
4402 macro_ptr_allocated
= str
.str
;
4409 /* end of macro or end of unget buffer */
4410 if (unget_buffer_enabled
) {
4411 macro_ptr
= unget_saved_macro_ptr
;
4412 unget_buffer_enabled
= 0;
4414 /* end of macro string: free it */
4415 tok_str_free(macro_ptr_allocated
);
4422 /* convert preprocessor tokens into C tokens */
4423 if (tok
== TOK_PPNUM
&&
4424 (parse_flags
& PARSE_FLAG_TOK_NUM
)) {
4425 parse_number((char *)tokc
.cstr
->data
);
4429 /* push back current token and set current token to 'last_tok'. Only
4430 identifier case handled for labels. */
4431 static inline void unget_tok(int last_tok
)
4435 unget_saved_macro_ptr
= macro_ptr
;
4436 unget_buffer_enabled
= 1;
4437 q
= unget_saved_buffer
;
4440 n
= tok_ext_size(tok
) - 1;
4443 *q
= 0; /* end of token string */
4448 void swap(int *p
, int *q
)
4456 void vsetc(CType
*type
, int r
, CValue
*vc
)
4460 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4461 error("memory full");
4462 /* cannot let cpu flags if other instruction are generated. Also
4463 avoid leaving VT_JMP anywhere except on the top of the stack
4464 because it would complicate the code generator. */
4465 if (vtop
>= vstack
) {
4466 v
= vtop
->r
& VT_VALMASK
;
4467 if (v
== VT_CMP
|| (v
& ~1) == VT_JMP
)
4473 vtop
->r2
= VT_CONST
;
4477 /* push integer constant */
4482 vsetc(&int_type
, VT_CONST
, &cval
);
4485 /* Return a static symbol pointing to a section */
4486 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
4487 unsigned long offset
, unsigned long size
)
4493 sym
= global_identifier_push(v
, type
->t
| VT_STATIC
, 0);
4494 sym
->type
.ref
= type
->ref
;
4495 sym
->r
= VT_CONST
| VT_SYM
;
4496 put_extern_sym(sym
, sec
, offset
, size
);
4500 /* push a reference to a section offset by adding a dummy symbol */
4501 static void vpush_ref(CType
*type
, Section
*sec
, unsigned long offset
, unsigned long size
)
4506 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4507 vtop
->sym
= get_sym_ref(type
, sec
, offset
, size
);
4510 /* define a new external reference to a symbol 'v' of type 'u' */
4511 static Sym
*external_global_sym(int v
, CType
*type
, int r
)
4517 /* push forward reference */
4518 s
= global_identifier_push(v
, type
->t
| VT_EXTERN
, 0);
4519 s
->type
.ref
= type
->ref
;
4520 s
->r
= r
| VT_CONST
| VT_SYM
;
4525 /* define a new external reference to a symbol 'v' of type 'u' */
4526 static Sym
*external_sym(int v
, CType
*type
, int r
)
4532 /* push forward reference */
4533 s
= sym_push(v
, type
, r
| VT_CONST
| VT_SYM
, 0);
4534 s
->type
.t
|= VT_EXTERN
;
4536 if (!is_compatible_types(&s
->type
, type
))
4537 error("incompatible types for redefinition of '%s'",
4538 get_tok_str(v
, NULL
));
4543 /* push a reference to global symbol v */
4544 static void vpush_global_sym(CType
*type
, int v
)
4549 sym
= external_global_sym(v
, type
, 0);
4551 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4555 void vset(CType
*type
, int r
, int v
)
4560 vsetc(type
, r
, &cval
);
4563 void vseti(int r
, int v
)
4579 void vpushv(SValue
*v
)
4581 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4582 error("memory full");
4592 /* save r to the memory stack, and mark it as being free */
4593 void save_reg(int r
)
4595 int l
, saved
, size
, align
;
4599 /* modify all stack values */
4602 for(p
=vstack
;p
<=vtop
;p
++) {
4603 if ((p
->r
& VT_VALMASK
) == r
||
4604 ((p
->type
.t
& VT_BTYPE
) == VT_LLONG
&& (p
->r2
& VT_VALMASK
) == r
)) {
4605 /* must save value on stack if not already done */
4607 /* NOTE: must reload 'r' because r might be equal to r2 */
4608 r
= p
->r
& VT_VALMASK
;
4609 /* store register in the stack */
4611 if ((p
->r
& VT_LVAL
) ||
4612 (!is_float(type
->t
) && (type
->t
& VT_BTYPE
) != VT_LLONG
))
4614 size
= type_size(type
, &align
);
4615 loc
= (loc
- size
) & -align
;
4616 sv
.type
.t
= type
->t
;
4617 sv
.r
= VT_LOCAL
| VT_LVAL
;
4620 #ifdef TCC_TARGET_I386
4621 /* x86 specific: need to pop fp register ST0 if saved */
4622 if (r
== TREG_ST0
) {
4623 o(0xd9dd); /* fstp %st(1) */
4626 /* special long long case */
4627 if ((type
->t
& VT_BTYPE
) == VT_LLONG
) {
4634 /* mark that stack entry as being saved on the stack */
4635 if (p
->r
& VT_LVAL
) {
4636 /* also clear the bounded flag because the
4637 relocation address of the function was stored in
4639 p
->r
= (p
->r
& ~(VT_VALMASK
| VT_BOUNDED
)) | VT_LLOCAL
;
4641 p
->r
= lvalue_type(p
->type
.t
) | VT_LOCAL
;
4649 /* find a register of class 'rc2' with at most one reference on stack.
4650 * If none, call get_reg(rc) */
4651 int get_reg_ex(int rc
, int rc2
)
4656 for(r
=0;r
<NB_REGS
;r
++) {
4657 if (reg_classes
[r
] & rc2
) {
4660 for(p
= vstack
; p
<= vtop
; p
++) {
4661 if ((p
->r
& VT_VALMASK
) == r
||
4662 (p
->r2
& VT_VALMASK
) == r
)
4672 /* find a free register of class 'rc'. If none, save one register */
4678 /* find a free register */
4679 for(r
=0;r
<NB_REGS
;r
++) {
4680 if (reg_classes
[r
] & rc
) {
4681 for(p
=vstack
;p
<=vtop
;p
++) {
4682 if ((p
->r
& VT_VALMASK
) == r
||
4683 (p
->r2
& VT_VALMASK
) == r
)
4691 /* no register left : free the first one on the stack (VERY
4692 IMPORTANT to start from the bottom to ensure that we don't
4693 spill registers used in gen_opi()) */
4694 for(p
=vstack
;p
<=vtop
;p
++) {
4695 r
= p
->r
& VT_VALMASK
;
4696 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
))
4698 /* also look at second register (if long long) */
4699 r
= p
->r2
& VT_VALMASK
;
4700 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
4706 /* Should never comes here */
4710 /* save registers up to (vtop - n) stack entry */
4711 void save_regs(int n
)
4716 for(p
= vstack
;p
<= p1
; p
++) {
4717 r
= p
->r
& VT_VALMASK
;
4724 /* move register 's' to 'r', and flush previous value of r to memory
4726 void move_reg(int r
, int s
)
4739 /* get address of vtop (vtop MUST BE an lvalue) */
4742 vtop
->r
&= ~VT_LVAL
;
4743 /* tricky: if saved lvalue, then we can go back to lvalue */
4744 if ((vtop
->r
& VT_VALMASK
) == VT_LLOCAL
)
4745 vtop
->r
= (vtop
->r
& ~(VT_VALMASK
| VT_LVAL_TYPE
)) | VT_LOCAL
| VT_LVAL
;
4748 #ifdef CONFIG_TCC_BCHECK
4749 /* generate lvalue bound code */
4755 vtop
->r
&= ~VT_MUSTBOUND
;
4756 /* if lvalue, then use checking code before dereferencing */
4757 if (vtop
->r
& VT_LVAL
) {
4758 /* if not VT_BOUNDED value, then make one */
4759 if (!(vtop
->r
& VT_BOUNDED
)) {
4760 lval_type
= vtop
->r
& (VT_LVAL_TYPE
| VT_LVAL
);
4761 /* must save type because we must set it to int to get pointer */
4763 vtop
->type
.t
= VT_INT
;
4766 gen_bounded_ptr_add();
4767 vtop
->r
|= lval_type
;
4770 /* then check for dereferencing */
4771 gen_bounded_ptr_deref();
4776 /* store vtop a register belonging to class 'rc'. lvalues are
4777 converted to values. Cannot be used if cannot be converted to
4778 register value (such as structures). */
4781 int r
, r2
, rc2
, bit_pos
, bit_size
, size
, align
, i
;
4782 unsigned long long ll
;
4784 /* NOTE: get_reg can modify vstack[] */
4785 if (vtop
->type
.t
& VT_BITFIELD
) {
4786 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
4787 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
4788 /* remove bit field info to avoid loops */
4789 vtop
->type
.t
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
4790 /* generate shifts */
4791 vpushi(32 - (bit_pos
+ bit_size
));
4793 vpushi(32 - bit_size
);
4794 /* NOTE: transformed to SHR if unsigned */
4798 if (is_float(vtop
->type
.t
) &&
4799 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4802 unsigned long offset
;
4804 /* XXX: unify with initializers handling ? */
4805 /* CPUs usually cannot use float constants, so we store them
4806 generically in data segment */
4807 size
= type_size(&vtop
->type
, &align
);
4808 offset
= (data_section
->data_offset
+ align
- 1) & -align
;
4809 data_section
->data_offset
= offset
;
4810 /* XXX: not portable yet */
4812 /* Zero pad x87 tenbyte long doubles */
4814 vtop
->c
.tab
[2] &= 0xffff;
4816 ptr
= section_ptr_add(data_section
, size
);
4819 ptr
[i
] = vtop
->c
.tab
[i
];
4820 sym
= get_sym_ref(&vtop
->type
, data_section
, offset
, size
<< 2);
4821 vtop
->r
|= VT_LVAL
| VT_SYM
;
4825 #ifdef CONFIG_TCC_BCHECK
4826 if (vtop
->r
& VT_MUSTBOUND
)
4830 r
= vtop
->r
& VT_VALMASK
;
4831 /* need to reload if:
4833 - lvalue (need to dereference pointer)
4834 - already a register, but not in the right class */
4835 if (r
>= VT_CONST
||
4836 (vtop
->r
& VT_LVAL
) ||
4837 !(reg_classes
[r
] & rc
) ||
4838 ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
&&
4839 !(reg_classes
[vtop
->r2
] & rc
))) {
4841 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
4842 /* two register type load : expand to two words
4844 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4847 vtop
->c
.ui
= ll
; /* first word */
4849 vtop
->r
= r
; /* save register value */
4850 vpushi(ll
>> 32); /* second word */
4851 } else if (r
>= VT_CONST
|| /* XXX: test to VT_CONST incorrect ? */
4852 (vtop
->r
& VT_LVAL
)) {
4853 /* We do not want to modifier the long long
4854 pointer here, so the safest (and less
4855 efficient) is to save all the other registers
4856 in the stack. XXX: totally inefficient. */
4858 /* load from memory */
4861 vtop
[-1].r
= r
; /* save register value */
4862 /* increment pointer to get second word */
4863 vtop
->type
.t
= VT_INT
;
4869 /* move registers */
4872 vtop
[-1].r
= r
; /* save register value */
4873 vtop
->r
= vtop
[-1].r2
;
4875 /* allocate second register */
4882 /* write second register */
4884 } else if ((vtop
->r
& VT_LVAL
) && !is_float(vtop
->type
.t
)) {
4886 /* lvalue of scalar type : need to use lvalue type
4887 because of possible cast */
4890 /* compute memory access type */
4891 if (vtop
->r
& VT_LVAL_BYTE
)
4893 else if (vtop
->r
& VT_LVAL_SHORT
)
4895 if (vtop
->r
& VT_LVAL_UNSIGNED
)
4899 /* restore wanted type */
4902 /* one register type load */
4907 #ifdef TCC_TARGET_C67
4908 /* uses register pairs for doubles */
4909 if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
)
4916 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4917 void gv2(int rc1
, int rc2
)
4921 /* generate more generic register first. But VT_JMP or VT_CMP
4922 values must be generated first in all cases to avoid possible
4924 v
= vtop
[0].r
& VT_VALMASK
;
4925 if (v
!= VT_CMP
&& (v
& ~1) != VT_JMP
&& rc1
<= rc2
) {
4930 /* test if reload is needed for first register */
4931 if ((vtop
[-1].r
& VT_VALMASK
) >= VT_CONST
) {
4941 /* test if reload is needed for first register */
4942 if ((vtop
[0].r
& VT_VALMASK
) >= VT_CONST
) {
4948 /* expand long long on stack in two int registers */
4953 u
= vtop
->type
.t
& VT_UNSIGNED
;
4956 vtop
[0].r
= vtop
[-1].r2
;
4957 vtop
[0].r2
= VT_CONST
;
4958 vtop
[-1].r2
= VT_CONST
;
4959 vtop
[0].type
.t
= VT_INT
| u
;
4960 vtop
[-1].type
.t
= VT_INT
| u
;
4963 #ifdef TCC_TARGET_ARM
4964 /* expand long long on stack */
4965 void lexpand_nr(void)
4969 u
= vtop
->type
.t
& VT_UNSIGNED
;
4971 vtop
->r2
= VT_CONST
;
4972 vtop
->type
.t
= VT_INT
| u
;
4973 v
=vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
);
4974 if (v
== VT_CONST
) {
4975 vtop
[-1].c
.ui
= vtop
->c
.ull
;
4976 vtop
->c
.ui
= vtop
->c
.ull
>> 32;
4978 } else if (v
== (VT_LVAL
|VT_CONST
) || v
== (VT_LVAL
|VT_LOCAL
)) {
4980 vtop
->r
= vtop
[-1].r
;
4981 } else if (v
> VT_CONST
) {
4985 vtop
->r
= vtop
[-1].r2
;
4986 vtop
[-1].r2
= VT_CONST
;
4987 vtop
[-1].type
.t
= VT_INT
| u
;
4991 /* build a long long from two ints */
4994 gv2(RC_INT
, RC_INT
);
4995 vtop
[-1].r2
= vtop
[0].r
;
4996 vtop
[-1].type
.t
= t
;
5000 /* rotate n first stack elements to the bottom
5001 I1 ... In -> I2 ... In I1 [top is right]
5009 for(i
=-n
+1;i
!=0;i
++)
5010 vtop
[i
] = vtop
[i
+1];
5014 /* rotate n first stack elements to the top
5015 I1 ... In -> In I1 ... I(n-1) [top is right]
5023 for(i
= 0;i
< n
- 1; i
++)
5024 vtop
[-i
] = vtop
[-i
- 1];
5028 #ifdef TCC_TARGET_ARM
5029 /* like vrott but in other direction
5030 In ... I1 -> I(n-1) ... I1 In [top is right]
5038 for(i
= n
- 1; i
> 0; i
--)
5039 vtop
[-i
] = vtop
[-i
+ 1];
5044 /* pop stack value */
5048 v
= vtop
->r
& VT_VALMASK
;
5049 #ifdef TCC_TARGET_I386
5050 /* for x86, we need to pop the FP stack */
5051 if (v
== TREG_ST0
&& !nocode_wanted
) {
5052 o(0xd9dd); /* fstp %st(1) */
5055 if (v
== VT_JMP
|| v
== VT_JMPI
) {
5056 /* need to put correct jump if && or || without test */
5062 /* convert stack entry to register and duplicate its value in another
5070 if ((t
& VT_BTYPE
) == VT_LLONG
) {
5077 /* stack: H L L1 H1 */
5085 /* duplicate value */
5096 load(r1
, &sv
); /* move r to r1 */
5098 /* duplicates value */
5103 /* generate CPU independent (unsigned) long long operations */
5104 void gen_opl(int op
)
5106 int t
, a
, b
, op1
, c
, i
;
5113 func
= TOK___divdi3
;
5116 func
= TOK___udivdi3
;
5119 func
= TOK___moddi3
;
5122 func
= TOK___umoddi3
;
5124 /* call generic long long function */
5125 vpush_global_sym(&func_old_type
, func
);
5130 vtop
->r2
= REG_LRET
;
5143 /* stack: L1 H1 L2 H2 */
5148 vtop
[-2] = vtop
[-3];
5151 /* stack: H1 H2 L1 L2 */
5157 /* stack: H1 H2 L1 L2 ML MH */
5160 /* stack: ML MH H1 H2 L1 L2 */
5164 /* stack: ML MH H1 L2 H2 L1 */
5169 /* stack: ML MH M1 M2 */
5172 } else if (op
== '+' || op
== '-') {
5173 /* XXX: add non carry method too (for MIPS or alpha) */
5179 /* stack: H1 H2 (L1 op L2) */
5182 gen_op(op1
+ 1); /* TOK_xxxC2 */
5185 /* stack: H1 H2 (L1 op L2) */
5188 /* stack: (L1 op L2) H1 H2 */
5190 /* stack: (L1 op L2) (H1 op H2) */
5198 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
5199 t
= vtop
[-1].type
.t
;
5203 /* stack: L H shift */
5205 /* constant: simpler */
5206 /* NOTE: all comments are for SHL. the other cases are
5207 done by swaping words */
5218 if (op
!= TOK_SAR
) {
5251 /* XXX: should provide a faster fallback on x86 ? */
5254 func
= TOK___sardi3
;
5257 func
= TOK___shrdi3
;
5260 func
= TOK___shldi3
;
5266 /* compare operations */
5272 /* stack: L1 H1 L2 H2 */
5274 vtop
[-1] = vtop
[-2];
5276 /* stack: L1 L2 H1 H2 */
5279 /* when values are equal, we need to compare low words. since
5280 the jump is inverted, we invert the test too. */
5283 else if (op1
== TOK_GT
)
5285 else if (op1
== TOK_ULT
)
5287 else if (op1
== TOK_UGT
)
5292 if (op1
!= TOK_NE
) {
5296 /* generate non equal test */
5297 /* XXX: NOT PORTABLE yet */
5301 #if defined(TCC_TARGET_I386)
5302 b
= psym(0x850f, 0);
5303 #elif defined(TCC_TARGET_ARM)
5305 o(0x1A000000 | encbranch(ind
, 0, 1));
5306 #elif defined(TCC_TARGET_C67)
5307 error("not implemented");
5309 #error not supported
5313 /* compare low. Always unsigned */
5317 else if (op1
== TOK_LE
)
5319 else if (op1
== TOK_GT
)
5321 else if (op1
== TOK_GE
)
5331 /* handle integer constant optimizations and various machine
5333 void gen_opic(int op
)
5335 int c1
, c2
, t1
, t2
, n
, c
;
5337 long long l1
, l2
, l
;
5338 typedef unsigned long long U
;
5342 t1
= v1
->type
.t
& VT_BTYPE
;
5343 t2
= v2
->type
.t
& VT_BTYPE
;
5344 l1
= (t1
== VT_LLONG
) ? v1
->c
.ll
: v1
->c
.i
;
5345 l2
= (t2
== VT_LLONG
) ? v2
->c
.ll
: v2
->c
.i
;
5347 /* currently, we cannot do computations with forward symbols */
5348 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5349 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5352 case '+': l1
+= l2
; break;
5353 case '-': l1
-= l2
; break;
5354 case '&': l1
&= l2
; break;
5355 case '^': l1
^= l2
; break;
5356 case '|': l1
|= l2
; break;
5357 case '*': l1
*= l2
; break;
5364 /* if division by zero, generate explicit division */
5367 error("division by zero in constant");
5371 default: l1
/= l2
; break;
5372 case '%': l1
%= l2
; break;
5373 case TOK_UDIV
: l1
= (U
)l1
/ l2
; break;
5374 case TOK_UMOD
: l1
= (U
)l1
% l2
; break;
5377 case TOK_SHL
: l1
<<= l2
; break;
5378 case TOK_SHR
: l1
= (U
)l1
>> l2
; break;
5379 case TOK_SAR
: l1
>>= l2
; break;
5381 case TOK_ULT
: l1
= (U
)l1
< (U
)l2
; break;
5382 case TOK_UGE
: l1
= (U
)l1
>= (U
)l2
; break;
5383 case TOK_EQ
: l1
= l1
== l2
; break;
5384 case TOK_NE
: l1
= l1
!= l2
; break;
5385 case TOK_ULE
: l1
= (U
)l1
<= (U
)l2
; break;
5386 case TOK_UGT
: l1
= (U
)l1
> (U
)l2
; break;
5387 case TOK_LT
: l1
= l1
< l2
; break;
5388 case TOK_GE
: l1
= l1
>= l2
; break;
5389 case TOK_LE
: l1
= l1
<= l2
; break;
5390 case TOK_GT
: l1
= l1
> l2
; break;
5392 case TOK_LAND
: l1
= l1
&& l2
; break;
5393 case TOK_LOR
: l1
= l1
|| l2
; break;
5400 /* if commutative ops, put c2 as constant */
5401 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
5402 op
== '|' || op
== '*')) {
5404 c
= c1
, c1
= c2
, c2
= c
;
5405 l
= l1
, l1
= l2
, l2
= l
;
5407 /* Filter out NOP operations like x*1, x-0, x&-1... */
5408 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
5411 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
5412 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
5418 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
5419 /* try to use shifts instead of muls or divs */
5420 if (l2
> 0 && (l2
& (l2
- 1)) == 0) {
5429 else if (op
== TOK_PDIV
)
5435 } else if (c2
&& (op
== '+' || op
== '-') &&
5436 (vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) ==
5437 (VT_CONST
| VT_SYM
)) {
5438 /* symbol + constant case */
5445 if (!nocode_wanted
) {
5446 /* call low level op generator */
5447 if (t1
== VT_LLONG
|| t2
== VT_LLONG
)
5458 /* generate a floating point operation with constant propagation */
5459 void gen_opif(int op
)
5467 /* currently, we cannot do computations with forward symbols */
5468 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5469 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5471 if (v1
->type
.t
== VT_FLOAT
) {
5474 } else if (v1
->type
.t
== VT_DOUBLE
) {
5482 /* NOTE: we only do constant propagation if finite number (not
5483 NaN or infinity) (ANSI spec) */
5484 if (!ieee_finite(f1
) || !ieee_finite(f2
))
5488 case '+': f1
+= f2
; break;
5489 case '-': f1
-= f2
; break;
5490 case '*': f1
*= f2
; break;
5494 error("division by zero in constant");
5499 /* XXX: also handles tests ? */
5503 /* XXX: overflow test ? */
5504 if (v1
->type
.t
== VT_FLOAT
) {
5506 } else if (v1
->type
.t
== VT_DOUBLE
) {
5514 if (!nocode_wanted
) {
5522 static int pointed_size(CType
*type
)
5525 return type_size(pointed_type(type
), &align
);
5528 static inline int is_null_pointer(SValue
*p
)
5530 if ((p
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
5532 return ((p
->type
.t
& VT_BTYPE
) == VT_INT
&& p
->c
.i
== 0) ||
5533 ((p
->type
.t
& VT_BTYPE
) == VT_LLONG
&& p
->c
.ll
== 0);
5536 static inline int is_integer_btype(int bt
)
5538 return (bt
== VT_BYTE
|| bt
== VT_SHORT
||
5539 bt
== VT_INT
|| bt
== VT_LLONG
);
5542 /* check types for comparison or substraction of pointers */
5543 static void check_comparison_pointer_types(SValue
*p1
, SValue
*p2
, int op
)
5545 CType
*type1
, *type2
, tmp_type1
, tmp_type2
;
5548 /* null pointers are accepted for all comparisons as gcc */
5549 if (is_null_pointer(p1
) || is_null_pointer(p2
))
5553 bt1
= type1
->t
& VT_BTYPE
;
5554 bt2
= type2
->t
& VT_BTYPE
;
5555 /* accept comparison between pointer and integer with a warning */
5556 if ((is_integer_btype(bt1
) || is_integer_btype(bt2
)) && op
!= '-') {
5557 if (op
!= TOK_LOR
&& op
!= TOK_LAND
)
5558 warning("comparison between pointer and integer");
5562 /* both must be pointers or implicit function pointers */
5563 if (bt1
== VT_PTR
) {
5564 type1
= pointed_type(type1
);
5565 } else if (bt1
!= VT_FUNC
)
5566 goto invalid_operands
;
5568 if (bt2
== VT_PTR
) {
5569 type2
= pointed_type(type2
);
5570 } else if (bt2
!= VT_FUNC
) {
5572 error("invalid operands to binary %s", get_tok_str(op
, NULL
));
5574 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
5575 (type2
->t
& VT_BTYPE
) == VT_VOID
)
5579 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5580 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5581 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
5582 /* gcc-like error if '-' is used */
5584 goto invalid_operands
;
5586 warning("comparison of distinct pointer types lacks a cast");
5590 /* generic gen_op: handles types problems */
5593 int u
, t1
, t2
, bt1
, bt2
, t
;
5596 t1
= vtop
[-1].type
.t
;
5597 t2
= vtop
[0].type
.t
;
5598 bt1
= t1
& VT_BTYPE
;
5599 bt2
= t2
& VT_BTYPE
;
5601 if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
5602 /* at least one operand is a pointer */
5603 /* relationnal op: must be both pointers */
5604 if (op
>= TOK_ULT
&& op
<= TOK_LOR
) {
5605 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5606 /* pointers are handled are unsigned */
5607 t
= VT_INT
| VT_UNSIGNED
;
5610 /* if both pointers, then it must be the '-' op */
5611 if (bt1
== VT_PTR
&& bt2
== VT_PTR
) {
5613 error("cannot use pointers here");
5614 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5615 /* XXX: check that types are compatible */
5616 u
= pointed_size(&vtop
[-1].type
);
5618 /* set to integer type */
5619 vtop
->type
.t
= VT_INT
;
5623 /* exactly one pointer : must be '+' or '-'. */
5624 if (op
!= '-' && op
!= '+')
5625 error("cannot use pointers here");
5626 /* Put pointer as first operand */
5627 if (bt2
== VT_PTR
) {
5631 type1
= vtop
[-1].type
;
5632 /* XXX: cast to int ? (long long case) */
5633 vpushi(pointed_size(&vtop
[-1].type
));
5635 #ifdef CONFIG_TCC_BCHECK
5636 /* if evaluating constant expression, no code should be
5637 generated, so no bound check */
5638 if (do_bounds_check
&& !const_wanted
) {
5639 /* if bounded pointers, we generate a special code to
5646 gen_bounded_ptr_add();
5652 /* put again type if gen_opic() swaped operands */
5655 } else if (is_float(bt1
) || is_float(bt2
)) {
5656 /* compute bigger type and do implicit casts */
5657 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
5659 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
5664 /* floats can only be used for a few operations */
5665 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
5666 (op
< TOK_ULT
|| op
> TOK_GT
))
5667 error("invalid operands for binary operation");
5669 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
5670 /* cast to biggest op */
5672 /* convert to unsigned if it does not fit in a long long */
5673 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
5674 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
5678 /* integer operations */
5680 /* convert to unsigned if it does not fit in an integer */
5681 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
5682 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
5685 /* XXX: currently, some unsigned operations are explicit, so
5686 we modify them here */
5687 if (t
& VT_UNSIGNED
) {
5694 else if (op
== TOK_LT
)
5696 else if (op
== TOK_GT
)
5698 else if (op
== TOK_LE
)
5700 else if (op
== TOK_GE
)
5707 /* special case for shifts and long long: we keep the shift as
5709 if (op
== TOK_SHR
|| op
== TOK_SAR
|| op
== TOK_SHL
)
5716 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
5717 /* relationnal op: the result is an int */
5718 vtop
->type
.t
= VT_INT
;
5725 /* generic itof for unsigned long long case */
5726 void gen_cvt_itof1(int t
)
5728 if ((vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
)) ==
5729 (VT_LLONG
| VT_UNSIGNED
)) {
5732 vpush_global_sym(&func_old_type
, TOK___ulltof
);
5733 else if (t
== VT_DOUBLE
)
5734 vpush_global_sym(&func_old_type
, TOK___ulltod
);
5736 vpush_global_sym(&func_old_type
, TOK___ulltold
);
5746 /* generic ftoi for unsigned long long case */
5747 void gen_cvt_ftoi1(int t
)
5751 if (t
== (VT_LLONG
| VT_UNSIGNED
)) {
5752 /* not handled natively */
5753 st
= vtop
->type
.t
& VT_BTYPE
;
5755 vpush_global_sym(&func_old_type
, TOK___fixunssfdi
);
5756 else if (st
== VT_DOUBLE
)
5757 vpush_global_sym(&func_old_type
, TOK___fixunsdfdi
);
5759 vpush_global_sym(&func_old_type
, TOK___fixunsxfdi
);
5764 vtop
->r2
= REG_LRET
;
5770 /* force char or short cast */
5771 void force_charshort_cast(int t
)
5775 /* XXX: add optimization if lvalue : just change type and offset */
5780 if (t
& VT_UNSIGNED
) {
5781 vpushi((1 << bits
) - 1);
5787 /* result must be signed or the SAR is converted to an SHL
5788 This was not the case when "t" was a signed short
5789 and the last value on the stack was an unsigned int */
5790 vtop
->type
.t
&= ~VT_UNSIGNED
;
5796 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5797 static void gen_cast(CType
*type
)
5799 int sbt
, dbt
, sf
, df
, c
;
5801 /* special delayed cast for char/short */
5802 /* XXX: in some cases (multiple cascaded casts), it may still
5804 if (vtop
->r
& VT_MUSTCAST
) {
5805 vtop
->r
&= ~VT_MUSTCAST
;
5806 force_charshort_cast(vtop
->type
.t
);
5809 /* bitfields first get cast to ints */
5810 if (vtop
->type
.t
& VT_BITFIELD
) {
5814 dbt
= type
->t
& (VT_BTYPE
| VT_UNSIGNED
);
5815 sbt
= vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
);
5817 if (sbt
!= dbt
&& !nocode_wanted
) {
5820 c
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5822 /* convert from fp to fp */
5824 /* constant case: we can do it now */
5825 /* XXX: in ISOC, cannot do it if error in convert */
5826 if (dbt
== VT_FLOAT
&& sbt
== VT_DOUBLE
)
5827 vtop
->c
.f
= (float)vtop
->c
.d
;
5828 else if (dbt
== VT_FLOAT
&& sbt
== VT_LDOUBLE
)
5829 vtop
->c
.f
= (float)vtop
->c
.ld
;
5830 else if (dbt
== VT_DOUBLE
&& sbt
== VT_FLOAT
)
5831 vtop
->c
.d
= (double)vtop
->c
.f
;
5832 else if (dbt
== VT_DOUBLE
&& sbt
== VT_LDOUBLE
)
5833 vtop
->c
.d
= (double)vtop
->c
.ld
;
5834 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_FLOAT
)
5835 vtop
->c
.ld
= (long double)vtop
->c
.f
;
5836 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_DOUBLE
)
5837 vtop
->c
.ld
= (long double)vtop
->c
.d
;
5839 /* non constant case: generate code */
5843 /* convert int to fp */
5846 case VT_LLONG
| VT_UNSIGNED
:
5848 /* XXX: add const cases for long long */
5850 case VT_INT
| VT_UNSIGNED
:
5852 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.ui
; break;
5853 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.ui
; break;
5854 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.ui
; break;
5859 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.i
; break;
5860 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.i
; break;
5861 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.i
; break;
5867 #if !defined(TCC_TARGET_ARM)
5874 /* convert fp to int */
5875 if (dbt
== VT_BOOL
) {
5879 /* we handle char/short/etc... with generic code */
5880 if (dbt
!= (VT_INT
| VT_UNSIGNED
) &&
5881 dbt
!= (VT_LLONG
| VT_UNSIGNED
) &&
5886 case VT_LLONG
| VT_UNSIGNED
:
5888 /* XXX: add const cases for long long */
5890 case VT_INT
| VT_UNSIGNED
:
5892 case VT_FLOAT
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5893 case VT_DOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5894 case VT_LDOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5900 case VT_FLOAT
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5901 case VT_DOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5902 case VT_LDOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5910 if (dbt
== VT_INT
&& (type
->t
& (VT_BTYPE
| VT_UNSIGNED
)) != dbt
) {
5911 /* additional cast for char/short... */
5916 } else if ((dbt
& VT_BTYPE
) == VT_LLONG
) {
5917 if ((sbt
& VT_BTYPE
) != VT_LLONG
) {
5918 /* scalar to long long */
5920 if (sbt
== (VT_INT
| VT_UNSIGNED
))
5921 vtop
->c
.ll
= vtop
->c
.ui
;
5923 vtop
->c
.ll
= vtop
->c
.i
;
5925 /* machine independent conversion */
5927 /* generate high word */
5928 if (sbt
== (VT_INT
| VT_UNSIGNED
)) {
5936 /* patch second register */
5937 vtop
[-1].r2
= vtop
->r
;
5941 } else if (dbt
== VT_BOOL
) {
5942 /* scalar to bool */
5945 } else if ((dbt
& VT_BTYPE
) == VT_BYTE
||
5946 (dbt
& VT_BTYPE
) == VT_SHORT
) {
5947 if (sbt
== VT_PTR
) {
5948 vtop
->type
.t
= VT_INT
;
5949 warning("nonportable conversion from pointer to char/short");
5951 force_charshort_cast(dbt
);
5952 } else if ((dbt
& VT_BTYPE
) == VT_INT
) {
5954 if (sbt
== VT_LLONG
) {
5955 /* from long long: just take low order word */
5959 /* if lvalue and single word type, nothing to do because
5960 the lvalue already contains the real type size (see
5961 VT_LVAL_xxx constants) */
5963 } else if ((dbt
& VT_BTYPE
) == VT_PTR
&& !(vtop
->r
& VT_LVAL
)) {
5964 /* if we are casting between pointer types,
5965 we must update the VT_LVAL_xxx size */
5966 vtop
->r
= (vtop
->r
& ~VT_LVAL_TYPE
)
5967 | (lvalue_type(type
->ref
->type
.t
) & VT_LVAL_TYPE
);
5972 /* return type size. Put alignment at 'a' */
5973 static int type_size(CType
*type
, int *a
)
5978 bt
= type
->t
& VT_BTYPE
;
5979 if (bt
== VT_STRUCT
) {
5984 } else if (bt
== VT_PTR
) {
5985 if (type
->t
& VT_ARRAY
) {
5987 return type_size(&s
->type
, a
) * s
->c
;
5992 } else if (bt
== VT_LDOUBLE
) {
5994 return LDOUBLE_SIZE
;
5995 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
5996 #ifdef TCC_TARGET_I386
6002 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
6005 } else if (bt
== VT_SHORT
) {
6009 /* char, void, function, _Bool */
6015 /* return the pointed type of t */
6016 static inline CType
*pointed_type(CType
*type
)
6018 return &type
->ref
->type
;
6021 /* modify type so that its it is a pointer to type. */
6022 static void mk_pointer(CType
*type
)
6025 s
= sym_push(SYM_FIELD
, type
, 0, -1);
6026 type
->t
= VT_PTR
| (type
->t
& ~VT_TYPE
);
6030 /* compare function types. OLD functions match any new functions */
6031 static int is_compatible_func(CType
*type1
, CType
*type2
)
6037 if (!is_compatible_types(&s1
->type
, &s2
->type
))
6039 /* check func_call */
6042 /* XXX: not complete */
6043 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
6047 while (s1
!= NULL
) {
6050 if (!is_compatible_parameter_types(&s1
->type
, &s2
->type
))
6060 /* return true if type1 and type2 are the same. If unqualified is
6061 true, qualifiers on the types are ignored.
6063 - enums are not checked as gcc __builtin_types_compatible_p ()
6065 static int compare_types(CType
*type1
, CType
*type2
, int unqualified
)
6069 t1
= type1
->t
& VT_TYPE
;
6070 t2
= type2
->t
& VT_TYPE
;
6072 /* strip qualifiers before comparing */
6073 t1
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6074 t2
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6076 /* XXX: bitfields ? */
6079 /* test more complicated cases */
6080 bt1
= t1
& VT_BTYPE
;
6081 if (bt1
== VT_PTR
) {
6082 type1
= pointed_type(type1
);
6083 type2
= pointed_type(type2
);
6084 return is_compatible_types(type1
, type2
);
6085 } else if (bt1
== VT_STRUCT
) {
6086 return (type1
->ref
== type2
->ref
);
6087 } else if (bt1
== VT_FUNC
) {
6088 return is_compatible_func(type1
, type2
);
6094 /* return true if type1 and type2 are exactly the same (including
6097 static int is_compatible_types(CType
*type1
, CType
*type2
)
6099 return compare_types(type1
,type2
,0);
6102 /* return true if type1 and type2 are the same (ignoring qualifiers).
6104 static int is_compatible_parameter_types(CType
*type1
, CType
*type2
)
6106 return compare_types(type1
,type2
,1);
6109 /* print a type. If 'varstr' is not NULL, then the variable is also
6110 printed in the type */
6112 /* XXX: add array and function pointers */
6113 void type_to_str(char *buf
, int buf_size
,
6114 CType
*type
, const char *varstr
)
6121 t
= type
->t
& VT_TYPE
;
6124 if (t
& VT_CONSTANT
)
6125 pstrcat(buf
, buf_size
, "const ");
6126 if (t
& VT_VOLATILE
)
6127 pstrcat(buf
, buf_size
, "volatile ");
6128 if (t
& VT_UNSIGNED
)
6129 pstrcat(buf
, buf_size
, "unsigned ");
6159 tstr
= "long double";
6161 pstrcat(buf
, buf_size
, tstr
);
6165 if (bt
== VT_STRUCT
)
6169 pstrcat(buf
, buf_size
, tstr
);
6170 v
= type
->ref
->v
& ~SYM_STRUCT
;
6171 if (v
>= SYM_FIRST_ANOM
)
6172 pstrcat(buf
, buf_size
, "<anonymous>");
6174 pstrcat(buf
, buf_size
, get_tok_str(v
, NULL
));
6178 type_to_str(buf
, buf_size
, &s
->type
, varstr
);
6179 pstrcat(buf
, buf_size
, "(");
6181 while (sa
!= NULL
) {
6182 type_to_str(buf1
, sizeof(buf1
), &sa
->type
, NULL
);
6183 pstrcat(buf
, buf_size
, buf1
);
6186 pstrcat(buf
, buf_size
, ", ");
6188 pstrcat(buf
, buf_size
, ")");
6192 pstrcpy(buf1
, sizeof(buf1
), "*");
6194 pstrcat(buf1
, sizeof(buf1
), varstr
);
6195 type_to_str(buf
, buf_size
, &s
->type
, buf1
);
6199 pstrcat(buf
, buf_size
, " ");
6200 pstrcat(buf
, buf_size
, varstr
);
6205 /* verify type compatibility to store vtop in 'dt' type, and generate
6207 static void gen_assign_cast(CType
*dt
)
6209 CType
*st
, *type1
, *type2
, tmp_type1
, tmp_type2
;
6210 char buf1
[256], buf2
[256];
6213 st
= &vtop
->type
; /* source type */
6214 dbt
= dt
->t
& VT_BTYPE
;
6215 sbt
= st
->t
& VT_BTYPE
;
6216 if (dt
->t
& VT_CONSTANT
)
6217 warning("assignment of read-only location");
6220 /* special cases for pointers */
6221 /* '0' can also be a pointer */
6222 if (is_null_pointer(vtop
))
6224 /* accept implicit pointer to integer cast with warning */
6225 if (is_integer_btype(sbt
)) {
6226 warning("assignment makes pointer from integer without a cast");
6229 type1
= pointed_type(dt
);
6230 /* a function is implicitely a function pointer */
6231 if (sbt
== VT_FUNC
) {
6232 if ((type1
->t
& VT_BTYPE
) != VT_VOID
&&
6233 !is_compatible_types(pointed_type(dt
), st
))
6240 type2
= pointed_type(st
);
6241 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
6242 (type2
->t
& VT_BTYPE
) == VT_VOID
) {
6243 /* void * can match anything */
6245 /* exact type match, except for unsigned */
6248 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6249 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6250 if (!is_compatible_types(&tmp_type1
, &tmp_type2
))
6251 warning("assignment from incompatible pointer type");
6253 /* check const and volatile */
6254 if ((!(type1
->t
& VT_CONSTANT
) && (type2
->t
& VT_CONSTANT
)) ||
6255 (!(type1
->t
& VT_VOLATILE
) && (type2
->t
& VT_VOLATILE
)))
6256 warning("assignment discards qualifiers from pointer target type");
6262 if (sbt
== VT_PTR
|| sbt
== VT_FUNC
) {
6263 warning("assignment makes integer from pointer without a cast");
6265 /* XXX: more tests */
6270 tmp_type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6271 tmp_type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6272 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
6274 type_to_str(buf1
, sizeof(buf1
), st
, NULL
);
6275 type_to_str(buf2
, sizeof(buf2
), dt
, NULL
);
6276 error("cannot cast '%s' to '%s'", buf1
, buf2
);
6284 /* store vtop in lvalue pushed on stack */
6287 int sbt
, dbt
, ft
, r
, t
, size
, align
, bit_size
, bit_pos
, rc
, delayed_cast
;
6289 ft
= vtop
[-1].type
.t
;
6290 sbt
= vtop
->type
.t
& VT_BTYPE
;
6291 dbt
= ft
& VT_BTYPE
;
6292 if (((sbt
== VT_INT
|| sbt
== VT_SHORT
) && dbt
== VT_BYTE
) ||
6293 (sbt
== VT_INT
&& dbt
== VT_SHORT
)) {
6294 /* optimize char/short casts */
6295 delayed_cast
= VT_MUSTCAST
;
6296 vtop
->type
.t
= ft
& VT_TYPE
;
6297 /* XXX: factorize */
6298 if (ft
& VT_CONSTANT
)
6299 warning("assignment of read-only location");
6302 if (!(ft
& VT_BITFIELD
))
6303 gen_assign_cast(&vtop
[-1].type
);
6306 if (sbt
== VT_STRUCT
) {
6307 /* if structure, only generate pointer */
6308 /* structure assignment : generate memcpy */
6309 /* XXX: optimize if small size */
6310 if (!nocode_wanted
) {
6311 size
= type_size(&vtop
->type
, &align
);
6313 vpush_global_sym(&func_old_type
, TOK_memcpy
);
6317 vtop
->type
.t
= VT_INT
;
6321 vtop
->type
.t
= VT_INT
;
6333 /* leave source on stack */
6334 } else if (ft
& VT_BITFIELD
) {
6335 /* bitfield store handling */
6336 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
6337 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
6338 /* remove bit field info to avoid loops */
6339 vtop
[-1].type
.t
= ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
6341 /* duplicate source into other register */
6346 /* duplicate destination */
6348 vtop
[-1] = vtop
[-2];
6350 /* mask and shift source */
6351 vpushi((1 << bit_size
) - 1);
6355 /* load destination, mask and or with source */
6357 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
6363 /* pop off shifted source from "duplicate source..." above */
6367 #ifdef CONFIG_TCC_BCHECK
6368 /* bound check case */
6369 if (vtop
[-1].r
& VT_MUSTBOUND
) {
6375 if (!nocode_wanted
) {
6379 r
= gv(rc
); /* generate value */
6380 /* if lvalue was saved on stack, must read it */
6381 if ((vtop
[-1].r
& VT_VALMASK
) == VT_LLOCAL
) {
6383 t
= get_reg(RC_INT
);
6385 sv
.r
= VT_LOCAL
| VT_LVAL
;
6386 sv
.c
.ul
= vtop
[-1].c
.ul
;
6388 vtop
[-1].r
= t
| VT_LVAL
;
6391 /* two word case handling : store second register at word + 4 */
6392 if ((ft
& VT_BTYPE
) == VT_LLONG
) {
6394 /* convert to int to increment easily */
6395 vtop
->type
.t
= VT_INT
;
6401 /* XXX: it works because r2 is spilled last ! */
6402 store(vtop
->r2
, vtop
- 1);
6406 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
6407 vtop
->r
|= delayed_cast
;
6411 /* post defines POST/PRE add. c is the token ++ or -- */
6412 void inc(int post
, int c
)
6415 vdup(); /* save lvalue */
6417 gv_dup(); /* duplicate value */
6422 vpushi(c
- TOK_MID
);
6424 vstore(); /* store value */
6426 vpop(); /* if post op, return saved value */
6429 /* Parse GNUC __attribute__ extension. Currently, the following
6430 extensions are recognized:
6431 - aligned(n) : set data/function alignment.
6432 - packed : force data alignment to 1
6433 - section(x) : generate data/code in this section.
6434 - unused : currently ignored, but may be used someday.
6435 - regparm(n) : pass function parameters in registers (i386 only)
6437 static void parse_attribute(AttributeDef
*ad
)
6441 while (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
) {
6445 while (tok
!= ')') {
6446 if (tok
< TOK_IDENT
)
6447 expect("attribute name");
6455 expect("section name");
6456 ad
->section
= find_section(tcc_state
, (char *)tokc
.cstr
->data
);
6465 if (n
<= 0 || (n
& (n
- 1)) != 0)
6466 error("alignment must be a positive power of two");
6479 /* currently, no need to handle it because tcc does not
6480 track unused objects */
6484 /* currently, no need to handle it because tcc does not
6485 track unused objects */
6490 ad
->func_call
= FUNC_CDECL
;
6495 ad
->func_call
= FUNC_STDCALL
;
6497 #ifdef TCC_TARGET_I386
6507 ad
->func_call
= FUNC_FASTCALL1
+ n
- 1;
6513 ad
->func_call
= FUNC_FASTCALLW
;
6520 if (tcc_state
->warn_unsupported
)
6521 warning("'%s' attribute ignored", get_tok_str(t
, NULL
));
6522 /* skip parameters */
6524 int parenthesis
= 0;
6528 else if (tok
== ')')
6531 } while (parenthesis
&& tok
!= -1);
6544 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6545 static void struct_decl(CType
*type
, int u
)
6547 int a
, v
, size
, align
, maxalign
, c
, offset
;
6548 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
;
6549 Sym
*s
, *ss
, *ass
, **ps
;
6553 a
= tok
; /* save decl type */
6558 /* struct already defined ? return it */
6560 expect("struct/union/enum name");
6564 error("invalid type");
6571 /* we put an undefined size for struct/union */
6572 s
= sym_push(v
| SYM_STRUCT
, &type1
, 0, -1);
6573 s
->r
= 0; /* default alignment is zero as gcc */
6574 /* put struct/union/enum name in type */
6582 error("struct/union/enum already defined");
6583 /* cannot be empty */
6585 /* non empty enums are not allowed */
6586 if (a
== TOK_ENUM
) {
6590 expect("identifier");
6596 /* enum symbols have static storage */
6597 ss
= sym_push(v
, &int_type
, VT_CONST
, c
);
6598 ss
->type
.t
|= VT_STATIC
;
6603 /* NOTE: we accept a trailing comma */
6613 while (tok
!= '}') {
6614 parse_btype(&btype
, &ad
);
6620 type_decl(&type1
, &ad
, &v
, TYPE_DIRECT
| TYPE_ABSTRACT
);
6621 if (v
== 0 && (type1
.t
& VT_BTYPE
) != VT_STRUCT
)
6622 expect("identifier");
6623 if ((type1
.t
& VT_BTYPE
) == VT_FUNC
||
6624 (type1
.t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
| VT_INLINE
)))
6625 error("invalid type for '%s'",
6626 get_tok_str(v
, NULL
));
6630 bit_size
= expr_const();
6631 /* XXX: handle v = 0 case for messages */
6633 error("negative width in bit-field '%s'",
6634 get_tok_str(v
, NULL
));
6635 if (v
&& bit_size
== 0)
6636 error("zero width for bit-field '%s'",
6637 get_tok_str(v
, NULL
));
6639 size
= type_size(&type1
, &align
);
6641 if (align
< ad
.aligned
)
6643 } else if (ad
.packed
) {
6645 } else if (*tcc_state
->pack_stack_ptr
) {
6646 if (align
> *tcc_state
->pack_stack_ptr
)
6647 align
= *tcc_state
->pack_stack_ptr
;
6650 if (bit_size
>= 0) {
6651 bt
= type1
.t
& VT_BTYPE
;
6657 error("bitfields must have scalar type");
6659 if (bit_size
> bsize
) {
6660 error("width of '%s' exceeds its type",
6661 get_tok_str(v
, NULL
));
6662 } else if (bit_size
== bsize
) {
6663 /* no need for bit fields */
6665 } else if (bit_size
== 0) {
6666 /* XXX: what to do if only padding in a
6668 /* zero size: means to pad */
6672 /* we do not have enough room ? */
6673 if ((bit_pos
+ bit_size
) > bsize
)
6676 /* XXX: handle LSB first */
6677 type1
.t
|= VT_BITFIELD
|
6678 (bit_pos
<< VT_STRUCT_SHIFT
) |
6679 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
6680 bit_pos
+= bit_size
;
6685 if (v
!= 0 || (type1
.t
& VT_BTYPE
) == VT_STRUCT
) {
6686 /* add new memory data only if starting
6688 if (lbit_pos
== 0) {
6689 if (a
== TOK_STRUCT
) {
6690 c
= (c
+ align
- 1) & -align
;
6699 if (align
> maxalign
)
6703 printf("add field %s offset=%d",
6704 get_tok_str(v
, NULL
), offset
);
6705 if (type1
.t
& VT_BITFIELD
) {
6706 printf(" pos=%d size=%d",
6707 (type1
.t
>> VT_STRUCT_SHIFT
) & 0x3f,
6708 (type1
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
6713 if (v
== 0 && (type1
.t
& VT_BTYPE
) == VT_STRUCT
) {
6715 while ((ass
= ass
->next
) != NULL
) {
6716 ss
= sym_push(ass
->v
, &ass
->type
, 0, offset
+ ass
->c
);
6721 ss
= sym_push(v
| SYM_FIELD
, &type1
, 0, offset
);
6725 if (tok
== ';' || tok
== TOK_EOF
)
6732 /* store size and alignment */
6733 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
6739 /* return 0 if no type declaration. otherwise, return the basic type
6742 static int parse_btype(CType
*type
, AttributeDef
*ad
)
6744 int t
, u
, type_found
, typespec_found
, typedef_found
;
6748 memset(ad
, 0, sizeof(AttributeDef
));
6756 /* currently, we really ignore extension */
6766 if ((t
& VT_BTYPE
) != 0)
6767 error("too many basic types");
6783 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
6784 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6785 } else if ((t
& VT_BTYPE
) == VT_LONG
) {
6786 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
6800 if ((t
& VT_BTYPE
) == VT_LONG
) {
6801 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6808 struct_decl(&type1
, VT_ENUM
);
6811 type
->ref
= type1
.ref
;
6815 struct_decl(&type1
, VT_STRUCT
);
6818 /* type modifiers */
6871 /* GNUC attribute */
6872 case TOK_ATTRIBUTE1
:
6873 case TOK_ATTRIBUTE2
:
6874 parse_attribute(ad
);
6881 parse_expr_type(&type1
);
6884 if (typespec_found
|| typedef_found
)
6887 if (!s
|| !(s
->type
.t
& VT_TYPEDEF
))
6890 t
|= (s
->type
.t
& ~VT_TYPEDEF
);
6891 type
->ref
= s
->type
.ref
;
6899 if ((t
& (VT_SIGNED
|VT_UNSIGNED
)) == (VT_SIGNED
|VT_UNSIGNED
))
6900 error("signed and unsigned modifier");
6901 if (tcc_state
->char_is_unsigned
) {
6902 if ((t
& (VT_SIGNED
|VT_UNSIGNED
|VT_BTYPE
)) == VT_BYTE
)
6907 /* long is never used as type */
6908 if ((t
& VT_BTYPE
) == VT_LONG
)
6909 t
= (t
& ~VT_BTYPE
) | VT_INT
;
6914 /* convert a function parameter type (array to pointer and function to
6915 function pointer) */
6916 static inline void convert_parameter_type(CType
*pt
)
6918 /* remove const and volatile qualifiers (XXX: const could be used
6919 to indicate a const function parameter */
6920 pt
->t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6921 /* array must be transformed to pointer according to ANSI C */
6923 if ((pt
->t
& VT_BTYPE
) == VT_FUNC
) {
6928 static void post_type(CType
*type
, AttributeDef
*ad
)
6931 Sym
**plast
, *s
, *first
;
6936 /* function declaration */
6943 /* read param name and compute offset */
6944 if (l
!= FUNC_OLD
) {
6945 if (!parse_btype(&pt
, &ad1
)) {
6947 error("invalid type");
6954 if ((pt
.t
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
6956 type_decl(&pt
, &ad1
, &n
, TYPE_DIRECT
| TYPE_ABSTRACT
);
6957 if ((pt
.t
& VT_BTYPE
) == VT_VOID
)
6958 error("parameter declared as void");
6963 expect("identifier");
6967 convert_parameter_type(&pt
);
6968 s
= sym_push(n
| SYM_FIELD
, &pt
, 0, 0);
6974 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
6981 /* if no parameters, then old type prototype */
6985 t1
= type
->t
& VT_STORAGE
;
6986 /* NOTE: const is ignored in returned type as it has a special
6987 meaning in gcc / C++ */
6988 type
->t
&= ~(VT_STORAGE
| VT_CONSTANT
);
6989 post_type(type
, ad
);
6990 /* we push a anonymous symbol which will contain the function prototype */
6991 s
= sym_push(SYM_FIELD
, type
, ad
->func_call
, l
);
6993 type
->t
= t1
| VT_FUNC
;
6995 } else if (tok
== '[') {
6996 /* array definition */
7002 error("invalid array size");
7005 /* parse next post type */
7006 t1
= type
->t
& VT_STORAGE
;
7007 type
->t
&= ~VT_STORAGE
;
7008 post_type(type
, ad
);
7010 /* we push a anonymous symbol which will contain the array
7012 s
= sym_push(SYM_FIELD
, type
, 0, n
);
7013 type
->t
= t1
| VT_ARRAY
| VT_PTR
;
7018 /* Parse a type declaration (except basic type), and return the type
7019 in 'type'. 'td' is a bitmask indicating which kind of type decl is
7020 expected. 'type' should contain the basic type. 'ad' is the
7021 attribute definition of the basic type. It can be modified by
7024 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
)
7027 CType type1
, *type2
;
7030 while (tok
== '*') {
7038 qualifiers
|= VT_CONSTANT
;
7043 qualifiers
|= VT_VOLATILE
;
7051 type
->t
|= qualifiers
;
7054 /* XXX: clarify attribute handling */
7055 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7056 parse_attribute(ad
);
7058 /* recursive type */
7059 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7060 type1
.t
= 0; /* XXX: same as int */
7063 /* XXX: this is not correct to modify 'ad' at this point, but
7064 the syntax is not clear */
7065 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7066 parse_attribute(ad
);
7067 type_decl(&type1
, ad
, v
, td
);
7070 /* type identifier */
7071 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
7075 if (!(td
& TYPE_ABSTRACT
))
7076 expect("identifier");
7080 post_type(type
, ad
);
7081 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7082 parse_attribute(ad
);
7085 /* append type at the end of type1 */
7098 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7099 static int lvalue_type(int t
)
7104 if (bt
== VT_BYTE
|| bt
== VT_BOOL
)
7106 else if (bt
== VT_SHORT
)
7110 if (t
& VT_UNSIGNED
)
7111 r
|= VT_LVAL_UNSIGNED
;
7115 /* indirection with full error checking and bound check */
7116 static void indir(void)
7118 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
) {
7119 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FUNC
)
7123 if ((vtop
->r
& VT_LVAL
) && !nocode_wanted
)
7125 vtop
->type
= *pointed_type(&vtop
->type
);
7126 /* Arrays and functions are never lvalues */
7127 if (!(vtop
->type
.t
& VT_ARRAY
)
7128 && (vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
) {
7129 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7130 /* if bound checking, the referenced pointer must be checked */
7131 if (do_bounds_check
)
7132 vtop
->r
|= VT_MUSTBOUND
;
7136 /* pass a parameter to a function and do type checking and casting */
7137 static void gfunc_param_typed(Sym
*func
, Sym
*arg
)
7142 func_type
= func
->c
;
7143 if (func_type
== FUNC_OLD
||
7144 (func_type
== FUNC_ELLIPSIS
&& arg
== NULL
)) {
7145 /* default casting : only need to convert float to double */
7146 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FLOAT
) {
7150 } else if (arg
== NULL
) {
7151 error("too many arguments to function");
7154 type
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
7155 gen_assign_cast(&type
);
7159 /* parse an expression of the form '(type)' or '(expr)' and return its
7161 static void parse_expr_type(CType
*type
)
7167 if (parse_btype(type
, &ad
)) {
7168 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7175 static void parse_type(CType
*type
)
7180 if (!parse_btype(type
, &ad
)) {
7183 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7186 static void vpush_tokc(int t
)
7190 vsetc(&type
, VT_CONST
, &tokc
);
7193 static void unary(void)
7195 int n
, t
, align
, size
, r
;
7200 /* XXX: GCC 2.95.3 does not generate a table although it should be
7214 vpush_tokc(VT_INT
| VT_UNSIGNED
);
7218 vpush_tokc(VT_LLONG
);
7222 vpush_tokc(VT_LLONG
| VT_UNSIGNED
);
7226 vpush_tokc(VT_FLOAT
);
7230 vpush_tokc(VT_DOUBLE
);
7234 vpush_tokc(VT_LDOUBLE
);
7237 case TOK___FUNCTION__
:
7239 goto tok_identifier
;
7245 /* special function name identifier */
7246 len
= strlen(funcname
) + 1;
7247 /* generate char[len] type */
7252 vpush_ref(&type
, data_section
, data_section
->data_offset
, len
);
7253 ptr
= section_ptr_add(data_section
, len
);
7254 memcpy(ptr
, funcname
, len
);
7259 #ifdef TCC_TARGET_PE
7260 t
= VT_SHORT
| VT_UNSIGNED
;
7266 /* string parsing */
7269 if (tcc_state
->warn_write_strings
)
7274 memset(&ad
, 0, sizeof(AttributeDef
));
7275 decl_initializer_alloc(&type
, &ad
, VT_CONST
, 2, 0, 0);
7280 if (parse_btype(&type
, &ad
)) {
7281 type_decl(&type
, &ad
, &n
, TYPE_ABSTRACT
);
7283 /* check ISOC99 compound literal */
7285 /* data is allocated locally by default */
7290 /* all except arrays are lvalues */
7291 if (!(type
.t
& VT_ARRAY
))
7292 r
|= lvalue_type(type
.t
);
7293 memset(&ad
, 0, sizeof(AttributeDef
));
7294 decl_initializer_alloc(&type
, &ad
, r
, 1, 0, 0);
7299 } else if (tok
== '{') {
7300 /* save all registers */
7302 /* statement expression : we do not accept break/continue
7303 inside as GCC does */
7304 block(NULL
, NULL
, NULL
, NULL
, 0, 1);
7319 /* functions names must be treated as function pointers,
7320 except for unary '&' and sizeof. Since we consider that
7321 functions are not lvalues, we only have to handle it
7322 there and in function calls. */
7323 /* arrays can also be used although they are not lvalues */
7324 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
&&
7325 !(vtop
->type
.t
& VT_ARRAY
) && !(vtop
->type
.t
& VT_LLOCAL
))
7327 mk_pointer(&vtop
->type
);
7333 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
)
7334 vtop
->c
.i
= !vtop
->c
.i
;
7335 else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
7336 vtop
->c
.i
= vtop
->c
.i
^ 1;
7339 vseti(VT_JMP
, gtst(1, 0));
7350 /* in order to force cast, we add zero */
7352 if ((vtop
->type
.t
& VT_BTYPE
) == VT_PTR
)
7353 error("pointer not accepted for unary plus");
7363 parse_expr_type(&type
);
7367 size
= type_size(&type
, &align
);
7368 if (t
== TOK_SIZEOF
) {
7370 error("sizeof applied to an incomplete type");
7375 vtop
->type
.t
|= VT_UNSIGNED
;
7378 case TOK_builtin_types_compatible_p
:
7387 type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7388 type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7389 vpushi(is_compatible_types(&type1
, &type2
));
7392 case TOK_builtin_constant_p
:
7394 int saved_nocode_wanted
, res
;
7397 saved_nocode_wanted
= nocode_wanted
;
7400 res
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
7402 nocode_wanted
= saved_nocode_wanted
;
7422 goto tok_identifier
;
7424 /* allow to take the address of a label */
7425 if (tok
< TOK_UIDENT
)
7426 expect("label identifier");
7427 s
= label_find(tok
);
7429 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
7431 if (s
->r
== LABEL_DECLARED
)
7432 s
->r
= LABEL_FORWARD
;
7435 s
->type
.t
= VT_VOID
;
7436 mk_pointer(&s
->type
);
7437 s
->type
.t
|= VT_STATIC
;
7439 vset(&s
->type
, VT_CONST
| VT_SYM
, 0);
7448 expect("identifier");
7452 error("'%s' undeclared", get_tok_str(t
, NULL
));
7453 /* for simple function calls, we tolerate undeclared
7454 external reference to int() function */
7455 if (tcc_state
->warn_implicit_function_declaration
)
7456 warning("implicit declaration of function '%s'",
7457 get_tok_str(t
, NULL
));
7458 s
= external_global_sym(t
, &func_old_type
, 0);
7460 if ((s
->type
.t
& (VT_STATIC
| VT_INLINE
| VT_BTYPE
)) ==
7461 (VT_STATIC
| VT_INLINE
| VT_FUNC
)) {
7462 /* if referencing an inline function, then we generate a
7463 symbol to it if not already done. It will have the
7464 effect to generate code for it at the end of the
7465 compilation unit. Inline function as always
7466 generated in the text section. */
7468 put_extern_sym(s
, text_section
, 0, 0);
7469 r
= VT_SYM
| VT_CONST
;
7473 vset(&s
->type
, r
, s
->c
);
7474 /* if forward reference, we must point to s */
7475 if (vtop
->r
& VT_SYM
) {
7482 /* post operations */
7484 if (tok
== TOK_INC
|| tok
== TOK_DEC
) {
7487 } else if (tok
== '.' || tok
== TOK_ARROW
) {
7489 if (tok
== TOK_ARROW
)
7494 /* expect pointer on structure */
7495 if ((vtop
->type
.t
& VT_BTYPE
) != VT_STRUCT
)
7496 expect("struct or union");
7500 while ((s
= s
->next
) != NULL
) {
7505 error("field not found");
7506 /* add field offset to pointer */
7507 vtop
->type
= char_pointer_type
; /* change type to 'char *' */
7510 /* change type to field type, and set to lvalue */
7511 vtop
->type
= s
->type
;
7512 /* an array is never an lvalue */
7513 if (!(vtop
->type
.t
& VT_ARRAY
)) {
7514 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7515 /* if bound checking, the referenced pointer must be checked */
7516 if (do_bounds_check
)
7517 vtop
->r
|= VT_MUSTBOUND
;
7520 } else if (tok
== '[') {
7526 } else if (tok
== '(') {
7532 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
) {
7533 /* pointer test (no array accepted) */
7534 if ((vtop
->type
.t
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
7535 vtop
->type
= *pointed_type(&vtop
->type
);
7536 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
)
7540 expect("function pointer");
7543 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
7545 /* get return type */
7548 sa
= s
->next
; /* first parameter */
7550 /* compute first implicit argument if a structure is returned */
7551 if ((s
->type
.t
& VT_BTYPE
) == VT_STRUCT
) {
7552 /* get some space for the returned structure */
7553 size
= type_size(&s
->type
, &align
);
7554 loc
= (loc
- size
) & -align
;
7556 ret
.r
= VT_LOCAL
| VT_LVAL
;
7557 /* pass it as 'int' to avoid structure arg passing
7559 vseti(VT_LOCAL
, loc
);
7565 /* return in register */
7566 if (is_float(ret
.type
.t
)) {
7569 if ((ret
.type
.t
& VT_BTYPE
) == VT_LLONG
)
7578 gfunc_param_typed(s
, sa
);
7588 error("too few arguments to function");
7590 if (!nocode_wanted
) {
7591 gfunc_call(nb_args
);
7593 vtop
-= (nb_args
+ 1);
7596 vsetc(&ret
.type
, ret
.r
, &ret
.c
);
7604 static void uneq(void)
7610 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
7611 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
7612 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
7627 static void expr_prod(void)
7632 while (tok
== '*' || tok
== '/' || tok
== '%') {
7640 static void expr_sum(void)
7645 while (tok
== '+' || tok
== '-') {
7653 static void expr_shift(void)
7658 while (tok
== TOK_SHL
|| tok
== TOK_SAR
) {
7666 static void expr_cmp(void)
7671 while ((tok
>= TOK_ULE
&& tok
<= TOK_GT
) ||
7672 tok
== TOK_ULT
|| tok
== TOK_UGE
) {
7680 static void expr_cmpeq(void)
7685 while (tok
== TOK_EQ
|| tok
== TOK_NE
) {
7693 static void expr_and(void)
7696 while (tok
== '&') {
7703 static void expr_xor(void)
7706 while (tok
== '^') {
7713 static void expr_or(void)
7716 while (tok
== '|') {
7723 /* XXX: fix this mess */
7724 static void expr_land_const(void)
7727 while (tok
== TOK_LAND
) {
7734 /* XXX: fix this mess */
7735 static void expr_lor_const(void)
7738 while (tok
== TOK_LOR
) {
7745 /* only used if non constant */
7746 static void expr_land(void)
7751 if (tok
== TOK_LAND
) {
7756 if (tok
!= TOK_LAND
) {
7766 static void expr_lor(void)
7771 if (tok
== TOK_LOR
) {
7776 if (tok
!= TOK_LOR
) {
7786 /* XXX: better constant handling */
7787 static void expr_eq(void)
7789 int tt
, u
, r1
, r2
, rc
, t1
, t2
, bt1
, bt2
;
7791 CType type
, type1
, type2
;
7800 if (tok
== ':' && gnu_ext
) {
7816 if (vtop
!= vstack
) {
7817 /* needed to avoid having different registers saved in
7819 if (is_float(vtop
->type
.t
))
7826 if (tok
== ':' && gnu_ext
) {
7834 sv
= *vtop
; /* save value to handle it later */
7835 vtop
--; /* no vpop so that FP stack is not flushed */
7843 bt1
= t1
& VT_BTYPE
;
7845 bt2
= t2
& VT_BTYPE
;
7846 /* cast operands to correct type according to ISOC rules */
7847 if (is_float(bt1
) || is_float(bt2
)) {
7848 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
7849 type
.t
= VT_LDOUBLE
;
7850 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
7855 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
7856 /* cast to biggest op */
7858 /* convert to unsigned if it does not fit in a long long */
7859 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
7860 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
7861 type
.t
|= VT_UNSIGNED
;
7862 } else if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
7863 /* XXX: test pointer compatibility */
7865 } else if (bt1
== VT_FUNC
|| bt2
== VT_FUNC
) {
7866 /* XXX: test function pointer compatibility */
7868 } else if (bt1
== VT_STRUCT
|| bt2
== VT_STRUCT
) {
7869 /* XXX: test structure compatibility */
7871 } else if (bt1
== VT_VOID
|| bt2
== VT_VOID
) {
7872 /* NOTE: as an extension, we accept void on only one side */
7875 /* integer operations */
7877 /* convert to unsigned if it does not fit in an integer */
7878 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
7879 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
7880 type
.t
|= VT_UNSIGNED
;
7883 /* now we convert second operand */
7885 if (VT_STRUCT
== (vtop
->type
.t
& VT_BTYPE
))
7888 if (is_float(type
.t
)) {
7890 } else if ((type
.t
& VT_BTYPE
) == VT_LLONG
) {
7891 /* for long longs, we use fixed registers to avoid having
7892 to handle a complicated move */
7897 /* this is horrible, but we must also convert first
7901 /* put again first value and cast it */
7904 if (VT_STRUCT
== (vtop
->type
.t
& VT_BTYPE
))
7914 static void gexpr(void)
7925 /* parse an expression and return its type without any side effect. */
7926 static void expr_type(CType
*type
)
7928 int saved_nocode_wanted
;
7930 saved_nocode_wanted
= nocode_wanted
;
7935 nocode_wanted
= saved_nocode_wanted
;
7938 /* parse a unary expression and return its type without any side
7940 static void unary_type(CType
*type
)
7952 /* parse a constant expression and return value in vtop. */
7953 static void expr_const1(void)
7962 /* parse an integer constant and return its value. */
7963 static int expr_const(void)
7967 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
7968 expect("constant expression");
7974 /* return the label token if current token is a label, otherwise
7976 static int is_label(void)
7980 /* fast test first */
7981 if (tok
< TOK_UIDENT
)
7983 /* no need to save tokc because tok is an identifier */
7990 unget_tok(last_tok
);
7995 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
7996 int case_reg
, int is_expr
)
8001 /* generate line number info */
8003 (last_line_num
!= file
->line_num
|| last_ind
!= ind
)) {
8004 put_stabn(N_SLINE
, 0, file
->line_num
, ind
- func_ind
);
8006 last_line_num
= file
->line_num
;
8010 /* default return value is (void) */
8012 vtop
->type
.t
= VT_VOID
;
8015 if (tok
== TOK_IF
) {
8022 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
8024 if (c
== TOK_ELSE
) {
8028 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
8029 gsym(d
); /* patch else jmp */
8032 } else if (tok
== TOK_WHILE
) {
8040 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8044 } else if (tok
== '{') {
8048 /* record local declaration stack position */
8050 llabel
= local_label_stack
;
8051 /* handle local labels declarations */
8052 if (tok
== TOK_LABEL
) {
8055 if (tok
< TOK_UIDENT
)
8056 expect("label identifier");
8057 label_push(&local_label_stack
, tok
, LABEL_DECLARED
);
8067 while (tok
!= '}') {
8072 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
8075 /* pop locally defined labels */
8076 label_pop(&local_label_stack
, llabel
);
8077 /* pop locally defined symbols */
8078 sym_pop(&local_stack
, s
);
8080 } else if (tok
== TOK_RETURN
) {
8084 gen_assign_cast(&func_vt
);
8085 if ((func_vt
.t
& VT_BTYPE
) == VT_STRUCT
) {
8087 /* if returning structure, must copy it to implicit
8088 first pointer arg location */
8091 vset(&type
, VT_LOCAL
| VT_LVAL
, func_vc
);
8094 /* copy structure value to pointer */
8096 } else if (is_float(func_vt
.t
)) {
8101 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
8104 rsym
= gjmp(rsym
); /* jmp */
8105 } else if (tok
== TOK_BREAK
) {
8108 error("cannot break");
8109 *bsym
= gjmp(*bsym
);
8112 } else if (tok
== TOK_CONTINUE
) {
8115 error("cannot continue");
8116 *csym
= gjmp(*csym
);
8119 } else if (tok
== TOK_FOR
) {
8146 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8151 if (tok
== TOK_DO
) {
8156 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8167 if (tok
== TOK_SWITCH
) {
8171 /* XXX: other types than integer */
8172 case_reg
= gv(RC_INT
);
8176 b
= gjmp(0); /* jump to first case */
8178 block(&a
, csym
, &b
, &c
, case_reg
, 0);
8179 /* if no default, jmp after switch */
8187 if (tok
== TOK_CASE
) {
8191 /* since a case is like a label, we must skip it with a jmp */
8197 if (gnu_ext
&& tok
== TOK_DOTS
) {
8201 warning("empty case range");
8211 *case_sym
= gtst(1, 0);
8217 if (tok
== TOK_CASE
) {
8221 *case_sym
= gtst(1, *case_sym
);
8224 goto block_after_label
;
8226 if (tok
== TOK_DEFAULT
) {
8232 error("too many 'default'");
8235 goto block_after_label
;
8237 if (tok
== TOK_GOTO
) {
8239 if (tok
== '*' && gnu_ext
) {
8243 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
8246 } else if (tok
>= TOK_UIDENT
) {
8247 s
= label_find(tok
);
8248 /* put forward definition if needed */
8250 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
8252 if (s
->r
== LABEL_DECLARED
)
8253 s
->r
= LABEL_FORWARD
;
8255 /* label already defined */
8256 if (s
->r
& LABEL_FORWARD
)
8257 s
->next
= (void *)gjmp((long)s
->next
);
8259 gjmp_addr((long)s
->next
);
8262 expect("label identifier");
8265 } else if (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
) {
8273 if (s
->r
== LABEL_DEFINED
)
8274 error("duplicate label '%s'", get_tok_str(s
->v
, NULL
));
8275 gsym((long)s
->next
);
8276 s
->r
= LABEL_DEFINED
;
8278 s
= label_push(&global_label_stack
, b
, LABEL_DEFINED
);
8280 s
->next
= (void *)ind
;
8281 /* we accept this, but it is a mistake */
8284 warning("deprecated use of label at end of compound statement");
8288 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
8291 /* expression case */
8306 /* t is the array or struct type. c is the array or struct
8307 address. cur_index/cur_field is the pointer to the current
8308 value. 'size_only' is true if only size info is needed (only used
8310 static void decl_designator(CType
*type
, Section
*sec
, unsigned long c
,
8311 int *cur_index
, Sym
**cur_field
,
8315 int notfirst
, index
, index_last
, align
, l
, nb_elems
, elem_size
;
8321 if (gnu_ext
&& (l
= is_label()) != 0)
8323 while (tok
== '[' || tok
== '.') {
8325 if (!(type
->t
& VT_ARRAY
))
8326 expect("array type");
8329 index
= expr_const();
8330 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
8331 expect("invalid index");
8332 if (tok
== TOK_DOTS
&& gnu_ext
) {
8334 index_last
= expr_const();
8335 if (index_last
< 0 ||
8336 (s
->c
>= 0 && index_last
>= s
->c
) ||
8338 expect("invalid index");
8344 *cur_index
= index_last
;
8345 type
= pointed_type(type
);
8346 elem_size
= type_size(type
, &align
);
8347 c
+= index
* elem_size
;
8348 /* NOTE: we only support ranges for last designator */
8349 nb_elems
= index_last
- index
+ 1;
8350 if (nb_elems
!= 1) {
8359 if ((type
->t
& VT_BTYPE
) != VT_STRUCT
)
8360 expect("struct/union type");
8373 /* XXX: fix this mess by using explicit storage field */
8375 type1
.t
|= (type
->t
& ~VT_TYPE
);
8389 if (type
->t
& VT_ARRAY
) {
8391 type
= pointed_type(type
);
8392 c
+= index
* type_size(type
, &align
);
8396 error("too many field init");
8397 /* XXX: fix this mess by using explicit storage field */
8399 type1
.t
|= (type
->t
& ~VT_TYPE
);
8404 decl_initializer(type
, sec
, c
, 0, size_only
);
8406 /* XXX: make it more general */
8407 if (!size_only
&& nb_elems
> 1) {
8408 unsigned long c_end
;
8413 error("range init not supported yet for dynamic storage");
8414 c_end
= c
+ nb_elems
* elem_size
;
8415 if (c_end
> sec
->data_allocated
)
8416 section_realloc(sec
, c_end
);
8417 src
= sec
->data
+ c
;
8419 for(i
= 1; i
< nb_elems
; i
++) {
8421 memcpy(dst
, src
, elem_size
);
8427 #define EXPR_CONST 1
8430 /* store a value or an expression directly in global data or in local array */
8431 static void init_putv(CType
*type
, Section
*sec
, unsigned long c
,
8432 int v
, int expr_type
)
8434 int saved_global_expr
, bt
, bit_pos
, bit_size
;
8436 unsigned long long bit_mask
;
8444 /* compound literals must be allocated globally in this case */
8445 saved_global_expr
= global_expr
;
8448 global_expr
= saved_global_expr
;
8449 /* NOTE: symbols are accepted */
8450 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) != VT_CONST
)
8451 error("initializer element is not constant");
8459 dtype
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
8462 /* XXX: not portable */
8463 /* XXX: generate error if incorrect relocation */
8464 gen_assign_cast(&dtype
);
8465 bt
= type
->t
& VT_BTYPE
;
8466 ptr
= sec
->data
+ c
;
8467 /* XXX: make code faster ? */
8468 if (!(type
->t
& VT_BITFIELD
)) {
8473 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
8474 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
8475 bit_mask
= (1LL << bit_size
) - 1;
8477 if ((vtop
->r
& VT_SYM
) &&
8483 (bt
== VT_INT
&& bit_size
!= 32)))
8484 error("initializer element is not computable at load time");
8487 *(char *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8490 *(short *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8493 *(double *)ptr
= vtop
->c
.d
;
8496 *(long double *)ptr
= vtop
->c
.ld
;
8499 *(long long *)ptr
|= (vtop
->c
.ll
& bit_mask
) << bit_pos
;
8502 if (vtop
->r
& VT_SYM
) {
8503 greloc(sec
, vtop
->sym
, c
, R_DATA_32
);
8505 *(int *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8510 vset(&dtype
, VT_LOCAL
|VT_LVAL
, c
);
8517 /* put zeros for variable based init */
8518 static void init_putz(CType
*t
, Section
*sec
, unsigned long c
, int size
)
8521 /* nothing to do because globals are already set to zero */
8523 vpush_global_sym(&func_old_type
, TOK_memset
);
8531 /* 't' contains the type and storage info. 'c' is the offset of the
8532 object in section 'sec'. If 'sec' is NULL, it means stack based
8533 allocation. 'first' is true if array '{' must be read (multi
8534 dimension implicit array init handling). 'size_only' is true if
8535 size only evaluation is wanted (only for arrays). */
8536 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
8537 int first
, int size_only
)
8539 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
8540 int size1
, align1
, expr_type
;
8544 if (type
->t
& VT_ARRAY
) {
8548 t1
= pointed_type(type
);
8549 size1
= type_size(t1
, &align1
);
8552 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
8558 /* only parse strings here if correct type (otherwise: handle
8559 them as ((w)char *) expressions */
8560 if ((tok
== TOK_LSTR
&&
8561 #ifdef TCC_TARGET_PE
8562 (t1
->t
& VT_BTYPE
) == VT_SHORT
&& (t1
->t
& VT_UNSIGNED
)) ||
8564 (t1
->t
& VT_BTYPE
) == VT_INT
) ||
8567 (t1
->t
& VT_BTYPE
) == VT_BYTE
)) {
8568 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8573 /* compute maximum number of chars wanted */
8575 cstr_len
= cstr
->size
;
8577 cstr_len
= cstr
->size
/ sizeof(nwchar_t
);
8580 if (n
>= 0 && nb
> (n
- array_length
))
8581 nb
= n
- array_length
;
8584 warning("initializer-string for array is too long");
8585 /* in order to go faster for common case (char
8586 string in global variable, we handle it
8588 if (sec
&& tok
== TOK_STR
&& size1
== 1) {
8589 memcpy(sec
->data
+ c
+ array_length
, cstr
->data
, nb
);
8593 ch
= ((unsigned char *)cstr
->data
)[i
];
8595 ch
= ((nwchar_t
*)cstr
->data
)[i
];
8596 init_putv(t1
, sec
, c
+ (array_length
+ i
) * size1
,
8604 /* only add trailing zero if enough storage (no
8605 warning in this case since it is standard) */
8606 if (n
< 0 || array_length
< n
) {
8608 init_putv(t1
, sec
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
8614 while (tok
!= '}') {
8615 decl_designator(type
, sec
, c
, &index
, NULL
, size_only
);
8616 if (n
>= 0 && index
>= n
)
8617 error("index too large");
8618 /* must put zero in holes (note that doing it that way
8619 ensures that it even works with designators) */
8620 if (!size_only
&& array_length
< index
) {
8621 init_putz(t1
, sec
, c
+ array_length
* size1
,
8622 (index
- array_length
) * size1
);
8625 if (index
> array_length
)
8626 array_length
= index
;
8627 /* special test for multi dimensional arrays (may not
8628 be strictly correct if designators are used at the
8630 if (index
>= n
&& no_oblock
)
8639 /* put zeros at the end */
8640 if (!size_only
&& n
>= 0 && array_length
< n
) {
8641 init_putz(t1
, sec
, c
+ array_length
* size1
,
8642 (n
- array_length
) * size1
);
8644 /* patch type size if needed */
8646 s
->c
= array_length
;
8647 } else if ((type
->t
& VT_BTYPE
) == VT_STRUCT
&&
8648 (sec
|| !first
|| tok
== '{')) {
8651 /* NOTE: the previous test is a specific case for automatic
8652 struct/union init */
8653 /* XXX: union needs only one init */
8655 /* XXX: this test is incorrect for local initializers
8656 beginning with ( without {. It would be much more difficult
8657 to do it correctly (ideally, the expression parser should
8658 be used in all cases) */
8664 while (tok
== '(') {
8668 if (!parse_btype(&type1
, &ad1
))
8670 type_decl(&type1
, &ad1
, &n
, TYPE_ABSTRACT
);
8672 if (!is_assignable_types(type
, &type1
))
8673 error("invalid type for cast");
8678 if (first
|| tok
== '{') {
8687 while (tok
!= '}') {
8688 decl_designator(type
, sec
, c
, NULL
, &f
, size_only
);
8690 if (!size_only
&& array_length
< index
) {
8691 init_putz(type
, sec
, c
+ array_length
,
8692 index
- array_length
);
8694 index
= index
+ type_size(&f
->type
, &align1
);
8695 if (index
> array_length
)
8696 array_length
= index
;
8698 if (no_oblock
&& f
== NULL
)
8704 /* put zeros at the end */
8705 if (!size_only
&& array_length
< n
) {
8706 init_putz(type
, sec
, c
+ array_length
,
8715 } else if (tok
== '{') {
8717 decl_initializer(type
, sec
, c
, first
, size_only
);
8719 } else if (size_only
) {
8720 /* just skip expression */
8722 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
8726 else if (tok
== ')')
8731 /* currently, we always use constant expression for globals
8732 (may change for scripting case) */
8733 expr_type
= EXPR_CONST
;
8735 expr_type
= EXPR_ANY
;
8736 init_putv(type
, sec
, c
, 0, expr_type
);
8740 /* parse an initializer for type 't' if 'has_init' is non zero, and
8741 allocate space in local or global data space ('r' is either
8742 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8743 variable 'v' of scope 'scope' is declared before initializers are
8744 parsed. If 'v' is zero, then a reference to the new object is put
8745 in the value stack. If 'has_init' is 2, a special parsing is done
8746 to handle string constants. */
8747 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
8748 int has_init
, int v
, int scope
)
8750 int size
, align
, addr
, data_offset
;
8752 ParseState saved_parse_state
;
8753 TokenString init_str
;
8756 size
= type_size(type
, &align
);
8757 /* If unknown size, we must evaluate it before
8758 evaluating initializers because
8759 initializers can generate global data too
8760 (e.g. string pointers or ISOC99 compound
8761 literals). It also simplifies local
8762 initializers handling */
8763 tok_str_new(&init_str
);
8766 error("unknown type size");
8767 /* get all init string */
8768 if (has_init
== 2) {
8769 /* only get strings */
8770 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8771 tok_str_add_tok(&init_str
);
8776 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
8778 error("unexpected end of file in initializer");
8779 tok_str_add_tok(&init_str
);
8782 else if (tok
== '}') {
8790 tok_str_add(&init_str
, -1);
8791 tok_str_add(&init_str
, 0);
8794 save_parse_state(&saved_parse_state
);
8796 macro_ptr
= init_str
.str
;
8798 decl_initializer(type
, NULL
, 0, 1, 1);
8799 /* prepare second initializer parsing */
8800 macro_ptr
= init_str
.str
;
8803 /* if still unknown size, error */
8804 size
= type_size(type
, &align
);
8806 error("unknown type size");
8808 /* take into account specified alignment if bigger */
8810 if (ad
->aligned
> align
)
8811 align
= ad
->aligned
;
8812 } else if (ad
->packed
) {
8815 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
8817 if (do_bounds_check
&& (type
->t
& VT_ARRAY
))
8819 loc
= (loc
- size
) & -align
;
8821 /* handles bounds */
8822 /* XXX: currently, since we do only one pass, we cannot track
8823 '&' operators, so we add only arrays */
8824 if (do_bounds_check
&& (type
->t
& VT_ARRAY
)) {
8825 unsigned long *bounds_ptr
;
8826 /* add padding between regions */
8828 /* then add local bound info */
8829 bounds_ptr
= section_ptr_add(lbounds_section
, 2 * sizeof(unsigned long));
8830 bounds_ptr
[0] = addr
;
8831 bounds_ptr
[1] = size
;
8834 /* local variable */
8835 sym_push(v
, type
, r
, addr
);
8837 /* push local reference */
8838 vset(type
, r
, addr
);
8844 if (v
&& scope
== VT_CONST
) {
8845 /* see if the symbol was already defined */
8848 if (!is_compatible_types(&sym
->type
, type
))
8849 error("incompatible types for redefinition of '%s'",
8850 get_tok_str(v
, NULL
));
8851 if (sym
->type
.t
& VT_EXTERN
) {
8852 /* if the variable is extern, it was not allocated */
8853 sym
->type
.t
&= ~VT_EXTERN
;
8854 /* set array size if it was ommited in extern
8856 if ((sym
->type
.t
& VT_ARRAY
) &&
8857 sym
->type
.ref
->c
< 0 &&
8859 sym
->type
.ref
->c
= type
->ref
->c
;
8861 /* we accept several definitions of the same
8862 global variable. this is tricky, because we
8863 must play with the SHN_COMMON type of the symbol */
8864 /* XXX: should check if the variable was already
8865 initialized. It is incorrect to initialized it
8867 /* no init data, we won't add more to the symbol */
8874 /* allocate symbol in corresponding section */
8879 else if (tcc_state
->nocommon
)
8883 data_offset
= sec
->data_offset
;
8884 data_offset
= (data_offset
+ align
- 1) & -align
;
8886 /* very important to increment global pointer at this time
8887 because initializers themselves can create new initializers */
8888 data_offset
+= size
;
8889 /* add padding if bound check */
8890 if (do_bounds_check
)
8892 sec
->data_offset
= data_offset
;
8893 /* allocate section space to put the data */
8894 if (sec
->sh_type
!= SHT_NOBITS
&&
8895 data_offset
> sec
->data_allocated
)
8896 section_realloc(sec
, data_offset
);
8897 /* align section if needed */
8898 if (align
> sec
->sh_addralign
)
8899 sec
->sh_addralign
= align
;
8901 addr
= 0; /* avoid warning */
8905 if (scope
!= VT_CONST
|| !sym
) {
8906 sym
= sym_push(v
, type
, r
| VT_SYM
, 0);
8908 /* update symbol definition */
8910 put_extern_sym(sym
, sec
, addr
, size
);
8913 /* put a common area */
8914 put_extern_sym(sym
, NULL
, align
, size
);
8915 /* XXX: find a nicer way */
8916 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
8917 esym
->st_shndx
= SHN_COMMON
;
8922 /* push global reference */
8923 sym
= get_sym_ref(type
, sec
, addr
, size
);
8925 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
8929 /* handles bounds now because the symbol must be defined
8930 before for the relocation */
8931 if (do_bounds_check
) {
8932 unsigned long *bounds_ptr
;
8934 greloc(bounds_section
, sym
, bounds_section
->data_offset
, R_DATA_32
);
8935 /* then add global bound info */
8936 bounds_ptr
= section_ptr_add(bounds_section
, 2 * sizeof(long));
8937 bounds_ptr
[0] = 0; /* relocated */
8938 bounds_ptr
[1] = size
;
8942 decl_initializer(type
, sec
, addr
, 1, 0);
8943 /* restore parse state if needed */
8945 tok_str_free(init_str
.str
);
8946 restore_parse_state(&saved_parse_state
);
8952 void put_func_debug(Sym
*sym
)
8957 /* XXX: we put here a dummy type */
8958 snprintf(buf
, sizeof(buf
), "%s:%c1",
8959 funcname
, sym
->type
.t
& VT_STATIC
? 'f' : 'F');
8960 put_stabs_r(buf
, N_FUN
, 0, file
->line_num
, 0,
8961 cur_text_section
, sym
->c
);
8966 /* parse an old style function declaration list */
8967 /* XXX: check multiple parameter */
8968 static void func_decl_list(Sym
*func_sym
)
8975 /* parse each declaration */
8976 while (tok
!= '{' && tok
!= ';' && tok
!= ',' && tok
!= TOK_EOF
) {
8977 if (!parse_btype(&btype
, &ad
))
8978 expect("declaration list");
8979 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
8980 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
8982 /* we accept no variable after */
8986 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
8987 /* find parameter in function parameter list */
8990 if ((s
->v
& ~SYM_FIELD
) == v
)
8994 error("declaration for parameter '%s' but no such parameter",
8995 get_tok_str(v
, NULL
));
8997 /* check that no storage specifier except 'register' was given */
8998 if (type
.t
& VT_STORAGE
)
8999 error("storage class specified for '%s'", get_tok_str(v
, NULL
));
9000 convert_parameter_type(&type
);
9001 /* we can add the type (NOTE: it could be local to the function) */
9003 /* accept other parameters */
9014 /* parse a function defined by symbol 'sym' and generate its code in
9015 'cur_text_section' */
9016 static void gen_function(Sym
*sym
)
9018 ind
= cur_text_section
->data_offset
;
9019 /* NOTE: we patch the symbol size later */
9020 put_extern_sym(sym
, cur_text_section
, ind
, 0);
9021 funcname
= get_tok_str(sym
->v
, NULL
);
9023 /* put debug symbol */
9025 put_func_debug(sym
);
9026 /* push a dummy symbol to enable local sym storage */
9027 sym_push2(&local_stack
, SYM_FIELD
, 0, 0);
9028 gfunc_prolog(&sym
->type
);
9030 block(NULL
, NULL
, NULL
, NULL
, 0, 0);
9033 cur_text_section
->data_offset
= ind
;
9034 label_pop(&global_label_stack
, NULL
);
9035 sym_pop(&local_stack
, NULL
); /* reset local stack */
9036 /* end of function */
9037 /* patch symbol size */
9038 ((Elf32_Sym
*)symtab_section
->data
)[sym
->c
].st_size
=
9041 put_stabn(N_FUN
, 0, 0, ind
- func_ind
);
9043 funcname
= ""; /* for safety */
9044 func_vt
.t
= VT_VOID
; /* for safety */
9045 ind
= 0; /* for safety */
9048 static void gen_inline_functions(void)
9052 int *str
, inline_generated
;
9054 /* iterate while inline function are referenced */
9056 inline_generated
= 0;
9057 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
9059 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
9060 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
9061 (VT_STATIC
| VT_INLINE
) &&
9063 /* the function was used: generate its code and
9064 convert it to a normal function */
9065 str
= (int *)sym
->r
;
9066 sym
->r
= VT_SYM
| VT_CONST
;
9067 type
->t
&= ~VT_INLINE
;
9071 cur_text_section
= text_section
;
9073 macro_ptr
= NULL
; /* fail safe */
9076 inline_generated
= 1;
9079 if (!inline_generated
)
9083 /* free all remaining inline function tokens */
9084 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
9086 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
9087 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
9088 (VT_STATIC
| VT_INLINE
)) {
9089 str
= (int *)sym
->r
;
9091 sym
->r
= 0; /* fail safe */
9096 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9097 static void decl(int l
)
9105 if (!parse_btype(&btype
, &ad
)) {
9106 /* skip redundant ';' */
9107 /* XXX: find more elegant solution */
9112 if (l
== VT_CONST
&&
9113 (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
)) {
9114 /* global asm block */
9118 /* special test for old K&R protos without explicit int
9119 type. Only accepted when defining global data */
9120 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
9124 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
9125 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
9127 /* we accept no variable after */
9131 while (1) { /* iterate thru each declaration */
9133 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
9137 type_to_str(buf
, sizeof(buf
), &type
, get_tok_str(v
, NULL
));
9138 printf("type = '%s'\n", buf
);
9141 if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9142 /* if old style function prototype, we accept a
9145 if (sym
->c
== FUNC_OLD
)
9146 func_decl_list(sym
);
9151 error("cannot use local functions");
9152 if ((type
.t
& VT_BTYPE
) != VT_FUNC
)
9153 expect("function definition");
9155 /* reject abstract declarators in function definition */
9157 while ((sym
= sym
->next
) != NULL
)
9158 if (!(sym
->v
& ~SYM_FIELD
))
9159 expect("identifier");
9161 /* XXX: cannot do better now: convert extern line to static inline */
9162 if ((type
.t
& (VT_EXTERN
| VT_INLINE
)) == (VT_EXTERN
| VT_INLINE
))
9163 type
.t
= (type
.t
& ~VT_EXTERN
) | VT_STATIC
;
9167 if ((sym
->type
.t
& VT_BTYPE
) != VT_FUNC
)
9169 /* specific case: if not func_call defined, we put
9170 the one of the prototype */
9171 /* XXX: should have default value */
9172 if (sym
->type
.ref
->r
!= FUNC_CDECL
&&
9173 type
.ref
->r
== FUNC_CDECL
)
9174 type
.ref
->r
= sym
->type
.ref
->r
;
9175 if (!is_compatible_types(&sym
->type
, &type
)) {
9177 error("incompatible types for redefinition of '%s'",
9178 get_tok_str(v
, NULL
));
9180 /* if symbol is already defined, then put complete type */
9183 /* put function symbol */
9184 sym
= global_identifier_push(v
, type
.t
, 0);
9185 sym
->type
.ref
= type
.ref
;
9188 /* static inline functions are just recorded as a kind
9189 of macro. Their code will be emitted at the end of
9190 the compilation unit only if they are used */
9191 if ((type
.t
& (VT_INLINE
| VT_STATIC
)) ==
9192 (VT_INLINE
| VT_STATIC
)) {
9193 TokenString func_str
;
9196 tok_str_new(&func_str
);
9202 error("unexpected end of file");
9203 tok_str_add_tok(&func_str
);
9208 } else if (t
== '}') {
9210 if (block_level
== 0)
9214 tok_str_add(&func_str
, -1);
9215 tok_str_add(&func_str
, 0);
9216 sym
->r
= (int)func_str
.str
;
9218 /* compute text section */
9219 cur_text_section
= ad
.section
;
9220 if (!cur_text_section
)
9221 cur_text_section
= text_section
;
9222 sym
->r
= VT_SYM
| VT_CONST
;
9224 #ifdef TCC_TARGET_PE
9226 ((Elf32_Sym
*)symtab_section
->data
)[sym
->c
].st_other
|= 1;
9232 if (btype
.t
& VT_TYPEDEF
) {
9233 /* save typedefed type */
9234 /* XXX: test storage specifiers ? */
9235 sym
= sym_push(v
, &type
, 0, 0);
9236 sym
->type
.t
|= VT_TYPEDEF
;
9237 } else if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9238 /* external function definition */
9239 /* specific case for func_call attribute */
9241 type
.ref
->r
= ad
.func_call
;
9242 external_sym(v
, &type
, 0);
9244 /* not lvalue if array */
9246 if (!(type
.t
& VT_ARRAY
))
9247 r
|= lvalue_type(type
.t
);
9248 has_init
= (tok
== '=');
9249 if ((btype
.t
& VT_EXTERN
) ||
9250 ((type
.t
& VT_ARRAY
) && (type
.t
& VT_STATIC
) &&
9251 !has_init
&& l
== VT_CONST
&& type
.ref
->c
< 0)) {
9252 /* external variable */
9253 /* NOTE: as GCC, uninitialized global static
9254 arrays of null size are considered as
9256 external_sym(v
, &type
, r
);
9258 type
.t
|= (btype
.t
& VT_STATIC
); /* Retain "static". */
9259 if (type
.t
& VT_STATIC
)
9265 decl_initializer_alloc(&type
, &ad
, r
,
9279 /* better than nothing, but needs extension to handle '-E' option
9281 static void preprocess_init(TCCState
*s1
)
9283 s1
->include_stack_ptr
= s1
->include_stack
;
9284 /* XXX: move that before to avoid having to initialize
9285 file->ifdef_stack_ptr ? */
9286 s1
->ifdef_stack_ptr
= s1
->ifdef_stack
;
9287 file
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
9289 /* XXX: not ANSI compliant: bound checking says error */
9291 s1
->pack_stack
[0] = 0;
9292 s1
->pack_stack_ptr
= s1
->pack_stack
;
9295 /* compile the C file opened in 'file'. Return non zero if errors. */
9296 static int tcc_compile(TCCState
*s1
)
9300 volatile int section_sym
;
9303 printf("%s: **** new file\n", file
->filename
);
9305 preprocess_init(s1
);
9308 anon_sym
= SYM_FIRST_ANOM
;
9310 /* file info: full path + filename */
9311 section_sym
= 0; /* avoid warning */
9313 section_sym
= put_elf_sym(symtab_section
, 0, 0,
9314 ELF32_ST_INFO(STB_LOCAL
, STT_SECTION
), 0,
9315 text_section
->sh_num
, NULL
);
9316 getcwd(buf
, sizeof(buf
));
9317 pstrcat(buf
, sizeof(buf
), "/");
9318 put_stabs_r(buf
, N_SO
, 0, 0,
9319 text_section
->data_offset
, text_section
, section_sym
);
9320 put_stabs_r(file
->filename
, N_SO
, 0, 0,
9321 text_section
->data_offset
, text_section
, section_sym
);
9323 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9324 symbols can be safely used */
9325 put_elf_sym(symtab_section
, 0, 0,
9326 ELF32_ST_INFO(STB_LOCAL
, STT_FILE
), 0,
9327 SHN_ABS
, file
->filename
);
9329 /* define some often used types */
9330 int_type
.t
= VT_INT
;
9332 char_pointer_type
.t
= VT_BYTE
;
9333 mk_pointer(&char_pointer_type
);
9335 func_old_type
.t
= VT_FUNC
;
9336 func_old_type
.ref
= sym_push(SYM_FIELD
, &int_type
, FUNC_CDECL
, FUNC_OLD
);
9339 /* define 'void *alloca(unsigned int)' builtin function */
9344 sym
= sym_push(p
, mk_pointer(VT_VOID
), FUNC_CDECL
, FUNC_NEW
);
9345 s1
= sym_push(SYM_FIELD
, VT_UNSIGNED
| VT_INT
, 0, 0);
9348 sym_push(TOK_alloca
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), VT_CONST
, 0);
9352 define_start
= define_stack
;
9354 if (setjmp(s1
->error_jmp_buf
) == 0) {
9356 s1
->error_set_jmp_enabled
= 1;
9358 ch
= file
->buf_ptr
[0];
9359 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
9360 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
;
9364 expect("declaration");
9366 /* end of translation unit info */
9368 put_stabs_r(NULL
, N_SO
, 0, 0,
9369 text_section
->data_offset
, text_section
, section_sym
);
9372 s1
->error_set_jmp_enabled
= 0;
9374 /* reset define stack, but leave -Dsymbols (may be incorrect if
9375 they are undefined) */
9376 free_defines(define_start
);
9378 gen_inline_functions();
9380 sym_pop(&global_stack
, NULL
);
9382 return s1
->nb_errors
!= 0 ? -1 : 0;
9385 /* Preprocess the current file */
9386 /* XXX: add line and file infos, add options to preserve spaces */
9387 static int tcc_preprocess(TCCState
*s1
)
9392 preprocess_init(s1
);
9394 define_start
= define_stack
;
9396 ch
= file
->buf_ptr
[0];
9397 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
9398 parse_flags
= PARSE_FLAG_ASM_COMMENTS
| PARSE_FLAG_PREPROCESS
|
9399 PARSE_FLAG_LINEFEED
;
9405 if (!last_is_space
) {
9406 fputc(' ', s1
->outfile
);
9408 fputs(get_tok_str(tok
, &tokc
), s1
->outfile
);
9409 if (tok
== TOK_LINEFEED
) {
9411 /* XXX: suppress that hack */
9412 parse_flags
&= ~PARSE_FLAG_LINEFEED
;
9414 parse_flags
|= PARSE_FLAG_LINEFEED
;
9421 free_defines(define_start
);
9427 int tcc_compile_string(TCCState
*s
, const char *str
)
9429 BufferedFile bf1
, *bf
= &bf1
;
9433 /* init file structure */
9435 /* XXX: avoid copying */
9437 buf
= tcc_malloc(len
+ 1);
9440 memcpy(buf
, str
, len
);
9443 bf
->buf_end
= buf
+ len
;
9444 pstrcpy(bf
->filename
, sizeof(bf
->filename
), "<string>");
9448 ret
= tcc_compile(s
);
9452 /* currently, no need to close */
9457 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9458 void tcc_define_symbol(TCCState
*s1
, const char *sym
, const char *value
)
9460 BufferedFile bf1
, *bf
= &bf1
;
9462 pstrcpy(bf
->buffer
, IO_BUF_SIZE
, sym
);
9463 pstrcat(bf
->buffer
, IO_BUF_SIZE
, " ");
9467 pstrcat(bf
->buffer
, IO_BUF_SIZE
, value
);
9469 /* init file structure */
9471 bf
->buf_ptr
= bf
->buffer
;
9472 bf
->buf_end
= bf
->buffer
+ strlen(bf
->buffer
);
9473 *bf
->buf_end
= CH_EOB
;
9474 bf
->filename
[0] = '\0';
9478 s1
->include_stack_ptr
= s1
->include_stack
;
9480 /* parse with define parser */
9481 ch
= file
->buf_ptr
[0];
9487 /* undefine a preprocessor symbol */
9488 void tcc_undefine_symbol(TCCState
*s1
, const char *sym
)
9492 ts
= tok_alloc(sym
, strlen(sym
));
9493 s
= define_find(ts
->tok
);
9494 /* undefine symbol by putting an invalid name */
9499 #ifdef CONFIG_TCC_ASM
9501 #ifdef TCC_TARGET_I386
9502 #include "i386-asm.c"
9507 static void asm_instr(void)
9509 error("inline asm() not supported");
9511 static void asm_global_instr(void)
9513 error("inline asm() not supported");
9519 #ifdef TCC_TARGET_COFF
9520 #include "tcccoff.c"
9523 #ifdef TCC_TARGET_PE
9527 /* print the position in the source file of PC value 'pc' by reading
9528 the stabs debug information */
9529 static void rt_printline(unsigned long wanted_pc
)
9531 Stab_Sym
*sym
, *sym_end
;
9532 char func_name
[128], last_func_name
[128];
9533 unsigned long func_addr
, last_pc
, pc
;
9534 const char *incl_files
[INCLUDE_STACK_SIZE
];
9535 int incl_index
, len
, last_line_num
, i
;
9536 const char *str
, *p
;
9538 fprintf(stderr
, "0x%08lx:", wanted_pc
);
9540 func_name
[0] = '\0';
9543 last_func_name
[0] = '\0';
9544 last_pc
= 0xffffffff;
9546 sym
= (Stab_Sym
*)stab_section
->data
+ 1;
9547 sym_end
= (Stab_Sym
*)(stab_section
->data
+ stab_section
->data_offset
);
9548 while (sym
< sym_end
) {
9549 switch(sym
->n_type
) {
9550 /* function start or end */
9552 if (sym
->n_strx
== 0) {
9553 /* we test if between last line and end of function */
9554 pc
= sym
->n_value
+ func_addr
;
9555 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
9557 func_name
[0] = '\0';
9560 str
= stabstr_section
->data
+ sym
->n_strx
;
9561 p
= strchr(str
, ':');
9563 pstrcpy(func_name
, sizeof(func_name
), str
);
9566 if (len
> sizeof(func_name
) - 1)
9567 len
= sizeof(func_name
) - 1;
9568 memcpy(func_name
, str
, len
);
9569 func_name
[len
] = '\0';
9571 func_addr
= sym
->n_value
;
9574 /* line number info */
9576 pc
= sym
->n_value
+ func_addr
;
9577 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
9580 last_line_num
= sym
->n_desc
;
9582 strcpy(last_func_name
, func_name
);
9586 str
= stabstr_section
->data
+ sym
->n_strx
;
9588 if (incl_index
< INCLUDE_STACK_SIZE
) {
9589 incl_files
[incl_index
++] = str
;
9597 if (sym
->n_strx
== 0) {
9598 incl_index
= 0; /* end of translation unit */
9600 str
= stabstr_section
->data
+ sym
->n_strx
;
9601 /* do not add path */
9603 if (len
> 0 && str
[len
- 1] != '/')
9611 /* second pass: we try symtab symbols (no line number info) */
9614 Elf32_Sym
*sym
, *sym_end
;
9617 sym_end
= (Elf32_Sym
*)(symtab_section
->data
+ symtab_section
->data_offset
);
9618 for(sym
= (Elf32_Sym
*)symtab_section
->data
+ 1;
9621 type
= ELF32_ST_TYPE(sym
->st_info
);
9622 if (type
== STT_FUNC
) {
9623 if (wanted_pc
>= sym
->st_value
&&
9624 wanted_pc
< sym
->st_value
+ sym
->st_size
) {
9625 pstrcpy(last_func_name
, sizeof(last_func_name
),
9626 strtab_section
->data
+ sym
->st_name
);
9632 /* did not find any info: */
9633 fprintf(stderr
, " ???\n");
9636 if (last_func_name
[0] != '\0') {
9637 fprintf(stderr
, " %s()", last_func_name
);
9639 if (incl_index
> 0) {
9640 fprintf(stderr
, " (%s:%d",
9641 incl_files
[incl_index
- 1], last_line_num
);
9642 for(i
= incl_index
- 2; i
>= 0; i
--)
9643 fprintf(stderr
, ", included from %s", incl_files
[i
]);
9644 fprintf(stderr
, ")");
9646 fprintf(stderr
, "\n");
9649 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
9653 /* fix for glibc 2.1 */
9659 /* return the PC at frame level 'level'. Return non zero if not found */
9660 static int rt_get_caller_pc(unsigned long *paddr
,
9661 ucontext_t
*uc
, int level
)
9667 #if defined(__FreeBSD__)
9668 *paddr
= uc
->uc_mcontext
.mc_eip
;
9669 #elif defined(__dietlibc__)
9670 *paddr
= uc
->uc_mcontext
.eip
;
9672 *paddr
= uc
->uc_mcontext
.gregs
[REG_EIP
];
9676 #if defined(__FreeBSD__)
9677 fp
= uc
->uc_mcontext
.mc_ebp
;
9678 #elif defined(__dietlibc__)
9679 fp
= uc
->uc_mcontext
.ebp
;
9681 fp
= uc
->uc_mcontext
.gregs
[REG_EBP
];
9683 for(i
=1;i
<level
;i
++) {
9684 /* XXX: check address validity with program info */
9685 if (fp
<= 0x1000 || fp
>= 0xc0000000)
9687 fp
= ((unsigned long *)fp
)[0];
9689 *paddr
= ((unsigned long *)fp
)[1];
9695 #warning add arch specific rt_get_caller_pc()
9697 static int rt_get_caller_pc(unsigned long *paddr
,
9698 ucontext_t
*uc
, int level
)
9704 /* emit a run time error at position 'pc' */
9705 void rt_error(ucontext_t
*uc
, const char *fmt
, ...)
9712 fprintf(stderr
, "Runtime error: ");
9713 vfprintf(stderr
, fmt
, ap
);
9714 fprintf(stderr
, "\n");
9715 for(i
=0;i
<num_callers
;i
++) {
9716 if (rt_get_caller_pc(&pc
, uc
, i
) < 0)
9719 fprintf(stderr
, "at ");
9721 fprintf(stderr
, "by ");
9728 /* signal handler for fatal errors */
9729 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
9731 ucontext_t
*uc
= puc
;
9735 switch(siginf
->si_code
) {
9738 rt_error(uc
, "division by zero");
9741 rt_error(uc
, "floating point exception");
9747 if (rt_bound_error_msg
&& *rt_bound_error_msg
)
9748 rt_error(uc
, *rt_bound_error_msg
);
9750 rt_error(uc
, "dereferencing invalid pointer");
9753 rt_error(uc
, "illegal instruction");
9756 rt_error(uc
, "abort() called");
9759 rt_error(uc
, "caught signal %d", signum
);
9766 /* do all relocations (needed before using tcc_get_symbol()) */
9767 int tcc_relocate(TCCState
*s1
)
9774 #ifdef TCC_TARGET_PE
9777 tcc_add_runtime(s1
);
9780 relocate_common_syms();
9782 tcc_add_linker_symbols(s1
);
9784 build_got_entries(s1
);
9786 /* compute relocation address : section are relocated in place. We
9787 also alloc the bss space */
9788 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9789 s
= s1
->sections
[i
];
9790 if (s
->sh_flags
& SHF_ALLOC
) {
9791 if (s
->sh_type
== SHT_NOBITS
)
9792 s
->data
= tcc_mallocz(s
->data_offset
);
9793 s
->sh_addr
= (unsigned long)s
->data
;
9797 relocate_syms(s1
, 1);
9799 if (s1
->nb_errors
!= 0)
9802 /* relocate each section */
9803 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9804 s
= s1
->sections
[i
];
9806 relocate_section(s1
, s
);
9809 /* mark executable sections as executable in memory */
9810 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9811 s
= s1
->sections
[i
];
9812 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_EXECINSTR
)) ==
9813 (SHF_ALLOC
| SHF_EXECINSTR
)) {
9816 unsigned long old_protect
;
9817 VirtualProtect(s
->data
, s
->data_offset
,
9818 PAGE_EXECUTE_READWRITE
, &old_protect
);
9822 unsigned long start
, end
;
9823 start
= (unsigned long)(s
->data
) & ~(PAGESIZE
- 1);
9824 end
= (unsigned long)(s
->data
+ s
->data_offset
);
9825 end
= (end
+ PAGESIZE
- 1) & ~(PAGESIZE
- 1);
9826 mprotect((void *)start
, end
- start
,
9827 PROT_READ
| PROT_WRITE
| PROT_EXEC
);
9835 /* launch the compiled program with the given arguments */
9836 int tcc_run(TCCState
*s1
, int argc
, char **argv
)
9838 int (*prog_main
)(int, char **);
9840 if (tcc_relocate(s1
) < 0)
9843 prog_main
= tcc_get_symbol_err(s1
, "main");
9846 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
9847 error("debug mode currently not available for Windows");
9849 struct sigaction sigact
;
9850 /* install TCC signal handlers to print debug info on fatal
9852 sigact
.sa_flags
= SA_SIGINFO
| SA_RESETHAND
;
9853 sigact
.sa_sigaction
= sig_error
;
9854 sigemptyset(&sigact
.sa_mask
);
9855 sigaction(SIGFPE
, &sigact
, NULL
);
9856 sigaction(SIGILL
, &sigact
, NULL
);
9857 sigaction(SIGSEGV
, &sigact
, NULL
);
9858 sigaction(SIGBUS
, &sigact
, NULL
);
9859 sigaction(SIGABRT
, &sigact
, NULL
);
9863 #ifdef CONFIG_TCC_BCHECK
9864 if (do_bounds_check
) {
9865 void (*bound_init
)(void);
9867 /* set error function */
9868 rt_bound_error_msg
= (void *)tcc_get_symbol_err(s1
,
9869 "__bound_error_msg");
9871 /* XXX: use .init section so that it also work in binary ? */
9872 bound_init
= (void *)tcc_get_symbol_err(s1
, "__bound_init");
9876 return (*prog_main
)(argc
, argv
);
9879 TCCState
*tcc_new(void)
9886 s
= tcc_mallocz(sizeof(TCCState
));
9890 s
->output_type
= TCC_OUTPUT_MEMORY
;
9892 /* init isid table */
9894 isidnum_table
[i
] = isid(i
) || isnum(i
);
9896 /* add all tokens */
9898 memset(hash_ident
, 0, TOK_HASH_SIZE
* sizeof(TokenSym
*));
9900 tok_ident
= TOK_IDENT
;
9909 ts
= tok_alloc(p
, r
- p
- 1);
9913 /* we add dummy defines for some special macros to speed up tests
9914 and to have working defined() */
9915 define_push(TOK___LINE__
, MACRO_OBJ
, NULL
, NULL
);
9916 define_push(TOK___FILE__
, MACRO_OBJ
, NULL
, NULL
);
9917 define_push(TOK___DATE__
, MACRO_OBJ
, NULL
, NULL
);
9918 define_push(TOK___TIME__
, MACRO_OBJ
, NULL
, NULL
);
9920 /* standard defines */
9921 tcc_define_symbol(s
, "__STDC__", NULL
);
9922 #if defined(TCC_TARGET_I386)
9923 tcc_define_symbol(s
, "__i386__", NULL
);
9925 #if defined(TCC_TARGET_ARM)
9926 tcc_define_symbol(s
, "__ARM_ARCH_4__", NULL
);
9927 tcc_define_symbol(s
, "__arm_elf__", NULL
);
9928 tcc_define_symbol(s
, "__arm_elf", NULL
);
9929 tcc_define_symbol(s
, "arm_elf", NULL
);
9930 tcc_define_symbol(s
, "__arm__", NULL
);
9931 tcc_define_symbol(s
, "__arm", NULL
);
9932 tcc_define_symbol(s
, "arm", NULL
);
9933 tcc_define_symbol(s
, "__APCS_32__", NULL
);
9936 tcc_define_symbol(s
, "__linux__", NULL
);
9937 tcc_define_symbol(s
, "linux", NULL
);
9939 /* tiny C specific defines */
9940 tcc_define_symbol(s
, "__TINYC__", NULL
);
9942 /* tiny C & gcc defines */
9943 tcc_define_symbol(s
, "__SIZE_TYPE__", "unsigned int");
9944 tcc_define_symbol(s
, "__PTRDIFF_TYPE__", "int");
9945 #ifdef TCC_TARGET_PE
9946 tcc_define_symbol(s
, "__WCHAR_TYPE__", "unsigned short");
9948 tcc_define_symbol(s
, "__WCHAR_TYPE__", "int");
9951 /* default library paths */
9952 #ifdef TCC_TARGET_PE
9955 snprintf(buf
, sizeof(buf
), "%s/lib", tcc_lib_path
);
9956 tcc_add_library_path(s
, buf
);
9959 tcc_add_library_path(s
, "/usr/local/lib");
9960 tcc_add_library_path(s
, "/usr/lib");
9961 tcc_add_library_path(s
, "/lib");
9964 /* no section zero */
9965 dynarray_add((void ***)&s
->sections
, &s
->nb_sections
, NULL
);
9967 /* create standard sections */
9968 text_section
= new_section(s
, ".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
9969 data_section
= new_section(s
, ".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
9970 bss_section
= new_section(s
, ".bss", SHT_NOBITS
, SHF_ALLOC
| SHF_WRITE
);
9972 /* symbols are always generated for linking stage */
9973 symtab_section
= new_symtab(s
, ".symtab", SHT_SYMTAB
, 0,
9975 ".hashtab", SHF_PRIVATE
);
9976 strtab_section
= symtab_section
->link
;
9978 /* private symbol table for dynamic symbols */
9979 s
->dynsymtab_section
= new_symtab(s
, ".dynsymtab", SHT_SYMTAB
, SHF_PRIVATE
,
9981 ".dynhashtab", SHF_PRIVATE
);
9982 s
->alacarte_link
= 1;
9984 #ifdef CHAR_IS_UNSIGNED
9985 s
->char_is_unsigned
= 1;
9987 #if defined(TCC_TARGET_PE) && 0
9988 /* XXX: currently the PE linker is not ready to support that */
9989 s
->leading_underscore
= 1;
9994 void tcc_delete(TCCState
*s1
)
9998 /* free -D defines */
10002 n
= tok_ident
- TOK_IDENT
;
10003 for(i
= 0; i
< n
; i
++)
10004 tcc_free(table_ident
[i
]);
10005 tcc_free(table_ident
);
10007 /* free all sections */
10009 free_section(symtab_section
->hash
);
10011 free_section(s1
->dynsymtab_section
->hash
);
10012 free_section(s1
->dynsymtab_section
->link
);
10013 free_section(s1
->dynsymtab_section
);
10015 for(i
= 1; i
< s1
->nb_sections
; i
++)
10016 free_section(s1
->sections
[i
]);
10017 tcc_free(s1
->sections
);
10019 /* free loaded dlls array */
10020 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++)
10021 tcc_free(s1
->loaded_dlls
[i
]);
10022 tcc_free(s1
->loaded_dlls
);
10024 /* library paths */
10025 for(i
= 0; i
< s1
->nb_library_paths
; i
++)
10026 tcc_free(s1
->library_paths
[i
]);
10027 tcc_free(s1
->library_paths
);
10029 /* cached includes */
10030 for(i
= 0; i
< s1
->nb_cached_includes
; i
++)
10031 tcc_free(s1
->cached_includes
[i
]);
10032 tcc_free(s1
->cached_includes
);
10034 for(i
= 0; i
< s1
->nb_include_paths
; i
++)
10035 tcc_free(s1
->include_paths
[i
]);
10036 tcc_free(s1
->include_paths
);
10038 for(i
= 0; i
< s1
->nb_sysinclude_paths
; i
++)
10039 tcc_free(s1
->sysinclude_paths
[i
]);
10040 tcc_free(s1
->sysinclude_paths
);
10045 int tcc_add_include_path(TCCState
*s1
, const char *pathname
)
10049 pathname1
= tcc_strdup(pathname
);
10050 dynarray_add((void ***)&s1
->include_paths
, &s1
->nb_include_paths
, pathname1
);
10054 int tcc_add_sysinclude_path(TCCState
*s1
, const char *pathname
)
10058 pathname1
= tcc_strdup(pathname
);
10059 dynarray_add((void ***)&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
, pathname1
);
10063 static int tcc_add_file_internal(TCCState
*s1
, const char *filename
, int flags
)
10065 const char *ext
, *filename1
;
10068 BufferedFile
*saved_file
;
10070 /* find source file type with extension */
10071 filename1
= strrchr(filename
, '/');
10075 filename1
= filename
;
10076 ext
= strrchr(filename1
, '.');
10080 /* open the file */
10082 file
= tcc_open(s1
, filename
);
10084 if (flags
& AFF_PRINT_ERROR
) {
10085 error_noabort("file '%s' not found", filename
);
10091 if (flags
& AFF_PREPROCESS
) {
10092 ret
= tcc_preprocess(s1
);
10093 } else if (!ext
|| !strcmp(ext
, "c")) {
10094 /* C file assumed */
10095 ret
= tcc_compile(s1
);
10097 #ifdef CONFIG_TCC_ASM
10098 if (!strcmp(ext
, "S")) {
10099 /* preprocessed assembler */
10100 ret
= tcc_assemble(s1
, 1);
10101 } else if (!strcmp(ext
, "s")) {
10102 /* non preprocessed assembler */
10103 ret
= tcc_assemble(s1
, 0);
10106 #ifdef TCC_TARGET_PE
10107 if (!strcmp(ext
, "def")) {
10108 ret
= pe_load_def_file(s1
, fdopen(file
->fd
, "rb"));
10113 /* assume executable format: auto guess file type */
10114 ret
= read(fd
, &ehdr
, sizeof(ehdr
));
10115 lseek(fd
, 0, SEEK_SET
);
10117 error_noabort("could not read header");
10119 } else if (ret
!= sizeof(ehdr
)) {
10120 goto try_load_script
;
10123 if (ehdr
.e_ident
[0] == ELFMAG0
&&
10124 ehdr
.e_ident
[1] == ELFMAG1
&&
10125 ehdr
.e_ident
[2] == ELFMAG2
&&
10126 ehdr
.e_ident
[3] == ELFMAG3
) {
10127 file
->line_num
= 0; /* do not display line number if error */
10128 if (ehdr
.e_type
== ET_REL
) {
10129 ret
= tcc_load_object_file(s1
, fd
, 0);
10130 } else if (ehdr
.e_type
== ET_DYN
) {
10131 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
10132 #ifdef TCC_TARGET_PE
10136 h
= dlopen(filename
, RTLD_GLOBAL
| RTLD_LAZY
);
10143 ret
= tcc_load_dll(s1
, fd
, filename
,
10144 (flags
& AFF_REFERENCED_DLL
) != 0);
10147 error_noabort("unrecognized ELF file");
10150 } else if (memcmp((char *)&ehdr
, ARMAG
, 8) == 0) {
10151 file
->line_num
= 0; /* do not display line number if error */
10152 ret
= tcc_load_archive(s1
, fd
);
10154 #ifdef TCC_TARGET_COFF
10155 if (*(uint16_t *)(&ehdr
) == COFF_C67_MAGIC
) {
10156 ret
= tcc_load_coff(s1
, fd
);
10160 /* as GNU ld, consider it is an ld script if not recognized */
10162 ret
= tcc_load_ldscript(s1
);
10164 error_noabort("unrecognized file type");
10179 int tcc_add_file(TCCState
*s
, const char *filename
)
10181 return tcc_add_file_internal(s
, filename
, AFF_PRINT_ERROR
);
10184 int tcc_add_library_path(TCCState
*s
, const char *pathname
)
10188 pathname1
= tcc_strdup(pathname
);
10189 dynarray_add((void ***)&s
->library_paths
, &s
->nb_library_paths
, pathname1
);
10193 /* find and load a dll. Return non zero if not found */
10194 /* XXX: add '-rpath' option support ? */
10195 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
)
10200 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
10201 snprintf(buf
, sizeof(buf
), "%s/%s",
10202 s
->library_paths
[i
], filename
);
10203 if (tcc_add_file_internal(s
, buf
, flags
) == 0)
10209 /* the library name is the same as the argument of the '-l' option */
10210 int tcc_add_library(TCCState
*s
, const char *libraryname
)
10215 /* first we look for the dynamic library if not static linking */
10216 if (!s
->static_link
) {
10217 #ifdef TCC_TARGET_PE
10218 snprintf(buf
, sizeof(buf
), "%s.def", libraryname
);
10220 snprintf(buf
, sizeof(buf
), "lib%s.so", libraryname
);
10222 if (tcc_add_dll(s
, buf
, 0) == 0)
10226 /* then we look for the static library */
10227 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
10228 snprintf(buf
, sizeof(buf
), "%s/lib%s.a",
10229 s
->library_paths
[i
], libraryname
);
10230 if (tcc_add_file_internal(s
, buf
, 0) == 0)
10236 int tcc_add_symbol(TCCState
*s
, const char *name
, unsigned long val
)
10238 add_elf_sym(symtab_section
, val
, 0,
10239 ELF32_ST_INFO(STB_GLOBAL
, STT_NOTYPE
), 0,
10244 int tcc_set_output_type(TCCState
*s
, int output_type
)
10246 s
->output_type
= output_type
;
10248 if (!s
->nostdinc
) {
10251 /* default include paths */
10252 /* XXX: reverse order needed if -isystem support */
10253 #ifndef TCC_TARGET_PE
10254 tcc_add_sysinclude_path(s
, "/usr/local/include");
10255 tcc_add_sysinclude_path(s
, "/usr/include");
10257 snprintf(buf
, sizeof(buf
), "%s/include", tcc_lib_path
);
10258 tcc_add_sysinclude_path(s
, buf
);
10259 #ifdef TCC_TARGET_PE
10260 snprintf(buf
, sizeof(buf
), "%s/include/winapi", tcc_lib_path
);
10261 tcc_add_sysinclude_path(s
, buf
);
10265 /* if bound checking, then add corresponding sections */
10266 #ifdef CONFIG_TCC_BCHECK
10267 if (do_bounds_check
) {
10268 /* define symbol */
10269 tcc_define_symbol(s
, "__BOUNDS_CHECKING_ON", NULL
);
10270 /* create bounds sections */
10271 bounds_section
= new_section(s
, ".bounds",
10272 SHT_PROGBITS
, SHF_ALLOC
);
10273 lbounds_section
= new_section(s
, ".lbounds",
10274 SHT_PROGBITS
, SHF_ALLOC
);
10278 if (s
->char_is_unsigned
) {
10279 tcc_define_symbol(s
, "__CHAR_UNSIGNED__", NULL
);
10282 /* add debug sections */
10285 stab_section
= new_section(s
, ".stab", SHT_PROGBITS
, 0);
10286 stab_section
->sh_entsize
= sizeof(Stab_Sym
);
10287 stabstr_section
= new_section(s
, ".stabstr", SHT_STRTAB
, 0);
10288 put_elf_str(stabstr_section
, "");
10289 stab_section
->link
= stabstr_section
;
10290 /* put first entry */
10291 put_stabs("", 0, 0, 0, 0);
10294 /* add libc crt1/crti objects */
10295 #ifndef TCC_TARGET_PE
10296 if ((output_type
== TCC_OUTPUT_EXE
|| output_type
== TCC_OUTPUT_DLL
) &&
10298 if (output_type
!= TCC_OUTPUT_DLL
)
10299 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crt1.o");
10300 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crti.o");
10306 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10307 #define FD_INVERT 0x0002 /* invert value before storing */
10309 typedef struct FlagDef
{
10315 static const FlagDef warning_defs
[] = {
10316 { offsetof(TCCState
, warn_unsupported
), 0, "unsupported" },
10317 { offsetof(TCCState
, warn_write_strings
), 0, "write-strings" },
10318 { offsetof(TCCState
, warn_error
), 0, "error" },
10319 { offsetof(TCCState
, warn_implicit_function_declaration
), WD_ALL
,
10320 "implicit-function-declaration" },
10323 static int set_flag(TCCState
*s
, const FlagDef
*flags
, int nb_flags
,
10324 const char *name
, int value
)
10331 if (r
[0] == 'n' && r
[1] == 'o' && r
[2] == '-') {
10335 for(i
= 0, p
= flags
; i
< nb_flags
; i
++, p
++) {
10336 if (!strcmp(r
, p
->name
))
10341 if (p
->flags
& FD_INVERT
)
10343 *(int *)((uint8_t *)s
+ p
->offset
) = value
;
10348 /* set/reset a warning */
10349 int tcc_set_warning(TCCState
*s
, const char *warning_name
, int value
)
10354 if (!strcmp(warning_name
, "all")) {
10355 for(i
= 0, p
= warning_defs
; i
< countof(warning_defs
); i
++, p
++) {
10356 if (p
->flags
& WD_ALL
)
10357 *(int *)((uint8_t *)s
+ p
->offset
) = 1;
10361 return set_flag(s
, warning_defs
, countof(warning_defs
),
10362 warning_name
, value
);
10366 static const FlagDef flag_defs
[] = {
10367 { offsetof(TCCState
, char_is_unsigned
), 0, "unsigned-char" },
10368 { offsetof(TCCState
, char_is_unsigned
), FD_INVERT
, "signed-char" },
10369 { offsetof(TCCState
, nocommon
), FD_INVERT
, "common" },
10370 { offsetof(TCCState
, leading_underscore
), 0, "leading-underscore" },
10373 /* set/reset a flag */
10374 int tcc_set_flag(TCCState
*s
, const char *flag_name
, int value
)
10376 return set_flag(s
, flag_defs
, countof(flag_defs
),
10380 /* extract the basename of a file */
10381 static char *tcc_basename(const char *name
)
10384 p
= strrchr(name
, '/');
10387 p
= strrchr(name
, '\\');
10396 #if !defined(LIBTCC)
10398 static int64_t getclock_us(void)
10403 return (tb
.time
* 1000LL + tb
.millitm
) * 1000LL;
10406 gettimeofday(&tv
, NULL
);
10407 return tv
.tv_sec
* 1000000LL + tv
.tv_usec
;
10413 printf("tcc version " TCC_VERSION
" - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10414 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10415 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10416 " [infile1 infile2...] [-run infile args...]\n"
10418 "General options:\n"
10419 " -v display current version\n"
10420 " -c compile only - generate an object file\n"
10421 " -o outfile set output filename\n"
10422 " -Bdir set tcc internal library path\n"
10423 " -bench output compilation statistics\n"
10424 " -run run compiled source\n"
10425 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10426 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10427 " -w disable all warnings\n"
10428 "Preprocessor options:\n"
10429 " -E preprocess only\n"
10430 " -Idir add include path 'dir'\n"
10431 " -Dsym[=val] define 'sym' with value 'val'\n"
10432 " -Usym undefine 'sym'\n"
10433 "Linker options:\n"
10434 " -Ldir add library path 'dir'\n"
10435 " -llib link with dynamic or static library 'lib'\n"
10436 " -shared generate a shared library\n"
10437 " -static static linking\n"
10438 " -rdynamic export all global symbols to dynamic linker\n"
10439 " -r relocatable output\n"
10440 "Debugger options:\n"
10441 " -g generate runtime debug info\n"
10442 #ifdef CONFIG_TCC_BCHECK
10443 " -b compile with built-in memory and bounds checker (implies -g)\n"
10445 " -bt N show N callers in stack traces\n"
10449 #define TCC_OPTION_HAS_ARG 0x0001
10450 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10452 typedef struct TCCOption
{
10480 TCC_OPTION_nostdinc
,
10481 TCC_OPTION_nostdlib
,
10482 TCC_OPTION_print_search_dirs
,
10483 TCC_OPTION_rdynamic
,
10491 static const TCCOption tcc_options
[] = {
10492 { "h", TCC_OPTION_HELP
, 0 },
10493 { "?", TCC_OPTION_HELP
, 0 },
10494 { "I", TCC_OPTION_I
, TCC_OPTION_HAS_ARG
},
10495 { "D", TCC_OPTION_D
, TCC_OPTION_HAS_ARG
},
10496 { "U", TCC_OPTION_U
, TCC_OPTION_HAS_ARG
},
10497 { "L", TCC_OPTION_L
, TCC_OPTION_HAS_ARG
},
10498 { "B", TCC_OPTION_B
, TCC_OPTION_HAS_ARG
},
10499 { "l", TCC_OPTION_l
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10500 { "bench", TCC_OPTION_bench
, 0 },
10501 { "bt", TCC_OPTION_bt
, TCC_OPTION_HAS_ARG
},
10502 #ifdef CONFIG_TCC_BCHECK
10503 { "b", TCC_OPTION_b
, 0 },
10505 { "g", TCC_OPTION_g
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10506 { "c", TCC_OPTION_c
, 0 },
10507 { "static", TCC_OPTION_static
, 0 },
10508 { "shared", TCC_OPTION_shared
, 0 },
10509 { "o", TCC_OPTION_o
, TCC_OPTION_HAS_ARG
},
10510 { "run", TCC_OPTION_run
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10511 { "rdynamic", TCC_OPTION_rdynamic
, 0 },
10512 { "r", TCC_OPTION_r
, 0 },
10513 { "Wl,", TCC_OPTION_Wl
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10514 { "W", TCC_OPTION_W
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10515 { "O", TCC_OPTION_O
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10516 { "m", TCC_OPTION_m
, TCC_OPTION_HAS_ARG
},
10517 { "f", TCC_OPTION_f
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10518 { "nostdinc", TCC_OPTION_nostdinc
, 0 },
10519 { "nostdlib", TCC_OPTION_nostdlib
, 0 },
10520 { "print-search-dirs", TCC_OPTION_print_search_dirs
, 0 },
10521 { "v", TCC_OPTION_v
, 0 },
10522 { "w", TCC_OPTION_w
, 0 },
10523 { "pipe", TCC_OPTION_pipe
, 0},
10524 { "E", TCC_OPTION_E
, 0},
10528 /* convert 'str' into an array of space separated strings */
10529 static int expand_args(char ***pargv
, const char *str
)
10538 while (is_space(*str
))
10543 while (*str
!= '\0' && !is_space(*str
))
10546 arg
= tcc_malloc(len
+ 1);
10547 memcpy(arg
, s1
, len
);
10549 dynarray_add((void ***)&argv
, &argc
, arg
);
10555 static char **files
;
10556 static int nb_files
, nb_libraries
;
10557 static int multiple_files
;
10558 static int print_search_dirs
;
10559 static int output_type
;
10560 static int reloc_output
;
10561 static const char *outfile
;
10563 int parse_args(TCCState
*s
, int argc
, char **argv
)
10566 const TCCOption
*popt
;
10567 const char *optarg
, *p1
, *r1
;
10572 if (optind
>= argc
) {
10573 if (nb_files
== 0 && !print_search_dirs
)
10578 r
= argv
[optind
++];
10580 /* add a new file */
10581 dynarray_add((void ***)&files
, &nb_files
, r
);
10582 if (!multiple_files
) {
10584 /* argv[0] will be this file */
10588 /* find option in table (match only the first chars */
10589 popt
= tcc_options
;
10593 error("invalid option -- '%s'", r
);
10606 if (popt
->flags
& TCC_OPTION_HAS_ARG
) {
10607 if (*r1
!= '\0' || (popt
->flags
& TCC_OPTION_NOSEP
)) {
10610 if (optind
>= argc
)
10611 error("argument to '%s' is missing", r
);
10612 optarg
= argv
[optind
++];
10620 switch(popt
->index
) {
10621 case TCC_OPTION_HELP
:
10626 if (tcc_add_include_path(s
, optarg
) < 0)
10627 error("too many include paths");
10632 sym
= (char *)optarg
;
10633 value
= strchr(sym
, '=');
10638 tcc_define_symbol(s
, sym
, value
);
10642 tcc_undefine_symbol(s
, optarg
);
10645 tcc_add_library_path(s
, optarg
);
10648 /* set tcc utilities path (mainly for tcc development) */
10649 tcc_lib_path
= optarg
;
10652 dynarray_add((void ***)&files
, &nb_files
, r
);
10655 case TCC_OPTION_bench
:
10658 case TCC_OPTION_bt
:
10659 num_callers
= atoi(optarg
);
10661 #ifdef CONFIG_TCC_BCHECK
10663 do_bounds_check
= 1;
10671 multiple_files
= 1;
10672 output_type
= TCC_OUTPUT_OBJ
;
10674 case TCC_OPTION_static
:
10675 s
->static_link
= 1;
10677 case TCC_OPTION_shared
:
10678 output_type
= TCC_OUTPUT_DLL
;
10681 multiple_files
= 1;
10685 /* generate a .o merging several output files */
10687 output_type
= TCC_OUTPUT_OBJ
;
10689 case TCC_OPTION_nostdinc
:
10692 case TCC_OPTION_nostdlib
:
10695 case TCC_OPTION_print_search_dirs
:
10696 print_search_dirs
= 1;
10698 case TCC_OPTION_run
:
10702 argc1
= expand_args(&argv1
, optarg
);
10704 parse_args(s
, argc1
, argv1
);
10706 multiple_files
= 0;
10707 output_type
= TCC_OUTPUT_MEMORY
;
10711 printf("tcc version %s\n", TCC_VERSION
);
10714 if (tcc_set_flag(s
, optarg
, 1) < 0 && s
->warn_unsupported
)
10715 goto unsupported_option
;
10718 if (tcc_set_warning(s
, optarg
, 1) < 0 &&
10719 s
->warn_unsupported
)
10720 goto unsupported_option
;
10725 case TCC_OPTION_rdynamic
:
10728 case TCC_OPTION_Wl
:
10731 if (strstart(optarg
, "-Ttext,", &p
)) {
10732 s
->text_addr
= strtoul(p
, NULL
, 16);
10733 s
->has_text_addr
= 1;
10734 } else if (strstart(optarg
, "--oformat,", &p
)) {
10735 if (strstart(p
, "elf32-", NULL
)) {
10736 s
->output_format
= TCC_OUTPUT_FORMAT_ELF
;
10737 } else if (!strcmp(p
, "binary")) {
10738 s
->output_format
= TCC_OUTPUT_FORMAT_BINARY
;
10740 #ifdef TCC_TARGET_COFF
10741 if (!strcmp(p
, "coff")) {
10742 s
->output_format
= TCC_OUTPUT_FORMAT_COFF
;
10746 error("target %s not found", p
);
10749 error("unsupported linker option '%s'", optarg
);
10754 output_type
= TCC_OUTPUT_PREPROCESS
;
10757 if (s
->warn_unsupported
) {
10758 unsupported_option
:
10759 warning("unsupported option '%s'", r
);
10768 int main(int argc
, char **argv
)
10772 int nb_objfiles
, ret
, optind
;
10773 char objfilename
[1024];
10774 int64_t start_time
= 0;
10777 /* on win32, we suppose the lib and includes are at the location
10780 static char path
[1024];
10783 GetModuleFileNameA(NULL
, path
, sizeof path
);
10784 p
= d
= strlwr(path
);
10787 if (*d
== '\\') *d
= '/', p
= d
;
10791 tcc_lib_path
= path
;
10796 output_type
= TCC_OUTPUT_EXE
;
10798 multiple_files
= 1;
10803 print_search_dirs
= 0;
10805 optind
= parse_args(s
, argc
- 1, argv
+ 1) + 1;
10807 if (print_search_dirs
) {
10808 /* enough for Linux kernel */
10809 printf("install: %s/\n", tcc_lib_path
);
10813 nb_objfiles
= nb_files
- nb_libraries
;
10815 /* if outfile provided without other options, we output an
10817 if (outfile
&& output_type
== TCC_OUTPUT_MEMORY
)
10818 output_type
= TCC_OUTPUT_EXE
;
10820 /* check -c consistency : only single file handled. XXX: checks file type */
10821 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
10822 /* accepts only a single input file */
10823 if (nb_objfiles
!= 1)
10824 error("cannot specify multiple files with -c");
10825 if (nb_libraries
!= 0)
10826 error("cannot specify libraries with -c");
10830 if (output_type
== TCC_OUTPUT_PREPROCESS
) {
10832 s
->outfile
= stdout
;
10834 s
->outfile
= fopen(outfile
, "wb");
10836 error("could not open '%s", outfile
);
10838 } else if (output_type
!= TCC_OUTPUT_MEMORY
) {
10840 /* compute default outfile name */
10841 pstrcpy(objfilename
, sizeof(objfilename
) - 1,
10843 tcc_basename(files
[0]));
10844 #ifdef TCC_TARGET_PE
10845 pe_guess_outfile(objfilename
, output_type
);
10847 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
10848 char *ext
= strrchr(objfilename
, '.');
10850 goto default_outfile
;
10851 /* add .o extension */
10852 strcpy(ext
+ 1, "o");
10855 pstrcpy(objfilename
, sizeof(objfilename
), "a.out");
10858 outfile
= objfilename
;
10863 start_time
= getclock_us();
10866 tcc_set_output_type(s
, output_type
);
10868 /* compile or add each files or library */
10869 for(i
= 0;i
< nb_files
; i
++) {
10870 const char *filename
;
10872 filename
= files
[i
];
10873 if (output_type
== TCC_OUTPUT_PREPROCESS
) {
10874 tcc_add_file_internal(s
, filename
,
10875 AFF_PRINT_ERROR
| AFF_PREPROCESS
);
10877 if (filename
[0] == '-') {
10878 if (tcc_add_library(s
, filename
+ 2) < 0)
10879 error("cannot find %s", filename
);
10881 if (tcc_add_file(s
, filename
) < 0) {
10889 /* free all files */
10894 total_time
= (double)(getclock_us() - start_time
) / 1000000.0;
10895 if (total_time
< 0.001)
10896 total_time
= 0.001;
10897 if (total_bytes
< 1)
10899 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10900 tok_ident
- TOK_IDENT
, total_lines
, total_bytes
,
10901 total_time
, (int)(total_lines
/ total_time
),
10902 total_bytes
/ total_time
/ 1000000.0);
10905 if (s
->output_type
== TCC_OUTPUT_PREPROCESS
) {
10907 fclose(s
->outfile
);
10909 } else if (s
->output_type
== TCC_OUTPUT_MEMORY
) {
10910 ret
= tcc_run(s
, argc
- optind
, argv
+ optind
);
10912 #ifdef TCC_TARGET_PE
10913 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
10914 ret
= tcc_output_pe(s
, outfile
);
10918 ret
= tcc_output_file(s
, outfile
) ? 1 : 0;
10921 /* XXX: cannot do it with bound checking because of the malloc hooks */
10922 if (!do_bounds_check
)
10927 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size
, mem_max_size
);