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>
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);
729 #define snprintf _snprintf
730 #define vsnprintf _vsnprintf
732 #define strtold (long double)strtod
733 #define strtof (float)strtod
734 #define strtoll (long long)strtol
736 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__)
737 /* currently incorrect */
738 long double strtold(const char *nptr
, char **endptr
)
740 return (long double)strtod(nptr
, endptr
);
742 float strtof(const char *nptr
, char **endptr
)
744 return (float)strtod(nptr
, endptr
);
747 /* XXX: need to define this to use them in non ISOC99 context */
748 extern float strtof (const char *__nptr
, char **__endptr
);
749 extern long double strtold (const char *__nptr
, char **__endptr
);
752 static char *pstrcpy(char *buf
, int buf_size
, const char *s
);
753 static char *pstrcat(char *buf
, int buf_size
, const char *s
);
754 static const char *tcc_basename(const char *name
);
756 static void next(void);
757 static void next_nomacro(void);
758 static void parse_expr_type(CType
*type
);
759 static void expr_type(CType
*type
);
760 static void unary_type(CType
*type
);
761 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
762 int case_reg
, int is_expr
);
763 static int expr_const(void);
764 static void expr_eq(void);
765 static void gexpr(void);
766 static void gen_inline_functions(void);
767 static void decl(int l
);
768 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
769 int first
, int size_only
);
770 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
771 int has_init
, int v
, int scope
);
773 void gv2(int rc1
, int rc2
);
774 void move_reg(int r
, int s
);
775 void save_regs(int n
);
776 void save_reg(int r
);
781 int get_reg_ex(int rc
,int rc2
);
784 struct macro_level
*prev
;
788 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
789 const int *macro_str
, struct macro_level
**can_read_stream
);
791 void force_charshort_cast(int t
);
792 static void gen_cast(CType
*type
);
794 static Sym
*sym_find(int v
);
795 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
);
798 static int type_size(CType
*type
, int *a
);
799 static inline CType
*pointed_type(CType
*type
);
800 static int pointed_size(CType
*type
);
801 static int lvalue_type(int t
);
802 static int parse_btype(CType
*type
, AttributeDef
*ad
);
803 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
);
804 static int is_compatible_types(CType
*type1
, CType
*type2
);
806 int ieee_finite(double d
);
807 void error(const char *fmt
, ...);
811 void lexpand_nr(void);
812 static void vpush_global_sym(CType
*type
, int v
);
813 void vset(CType
*type
, int r
, int v
);
814 void type_to_str(char *buf
, int buf_size
,
815 CType
*type
, const char *varstr
);
816 char *get_tok_str(int v
, CValue
*cv
);
817 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
818 unsigned long offset
, unsigned long size
);
819 static Sym
*external_global_sym(int v
, CType
*type
, int r
);
821 /* section generation */
822 static void section_realloc(Section
*sec
, unsigned long new_size
);
823 static void *section_ptr_add(Section
*sec
, unsigned long size
);
824 static void put_extern_sym(Sym
*sym
, Section
*section
,
825 unsigned long value
, unsigned long size
);
826 static void greloc(Section
*s
, Sym
*sym
, unsigned long addr
, int type
);
827 static int put_elf_str(Section
*s
, const char *sym
);
828 static int put_elf_sym(Section
*s
,
829 unsigned long value
, unsigned long size
,
830 int info
, int other
, int shndx
, const char *name
);
831 static int add_elf_sym(Section
*s
, unsigned long value
, unsigned long size
,
832 int info
, int other
, int sh_num
, const char *name
);
833 static void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
834 int type
, int symbol
);
835 static void put_stabs(const char *str
, int type
, int other
, int desc
,
836 unsigned long value
);
837 static void put_stabs_r(const char *str
, int type
, int other
, int desc
,
838 unsigned long value
, Section
*sec
, int sym_index
);
839 static void put_stabn(int type
, int other
, int desc
, int value
);
840 static void put_stabd(int type
, int other
, int desc
);
841 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
);
843 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
844 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
845 #define AFF_PREPROCESS 0x0004 /* preprocess file */
846 static int tcc_add_file_internal(TCCState
*s
, const char *filename
, int flags
);
849 int tcc_output_coff(TCCState
*s1
, FILE *f
);
852 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
);
853 int pe_load_def_file(struct TCCState
*s1
, FILE *fp
);
854 void pe_setup_paths(struct TCCState
*s1
, int *p_output_type
, const char **p_outfile
, char *first_file
);
855 unsigned long pe_add_runtime(struct TCCState
*s1
);
856 int tcc_output_pe(struct TCCState
*s1
, const char *filename
);
860 #ifdef CONFIG_TCC_ASM
862 typedef struct ExprValue
{
867 #define MAX_ASM_OPERANDS 30
869 typedef struct ASMOperand
{
870 int id
; /* GCC 3 optionnal identifier (0 if number only supported */
872 char asm_str
[16]; /* computed asm string for operand */
873 SValue
*vt
; /* C value of the expression */
874 int ref_index
; /* if >= 0, gives reference to a output constraint */
875 int input_index
; /* if >= 0, gives reference to an input constraint */
876 int priority
; /* priority, used to assign registers */
877 int reg
; /* if >= 0, register number used for this operand */
878 int is_llong
; /* true if double register value */
879 int is_memory
; /* true if memory operand */
880 int is_rw
; /* for '+' modifier */
883 static void asm_expr(TCCState
*s1
, ExprValue
*pe
);
884 static int asm_int_expr(TCCState
*s1
);
885 static int find_constraint(ASMOperand
*operands
, int nb_operands
,
886 const char *name
, const char **pp
);
888 static int tcc_assemble(TCCState
*s1
, int do_preprocess
);
892 static void asm_instr(void);
893 static void asm_global_instr(void);
895 /* true if float/double/long double type */
896 static inline int is_float(int t
)
900 return bt
== VT_LDOUBLE
|| bt
== VT_DOUBLE
|| bt
== VT_FLOAT
;
903 #ifdef TCC_TARGET_I386
904 #include "i386-gen.c"
907 #ifdef TCC_TARGET_ARM
911 #ifdef TCC_TARGET_C67
915 #ifdef CONFIG_TCC_STATIC
917 #define RTLD_LAZY 0x001
918 #define RTLD_NOW 0x002
919 #define RTLD_GLOBAL 0x100
920 #define RTLD_DEFAULT NULL
922 /* dummy function for profiling */
923 void *dlopen(const char *filename
, int flag
)
928 const char *dlerror(void)
933 typedef struct TCCSyms
{
938 #define TCCSYM(a) { #a, &a, },
940 /* add the symbol you want here if no dynamic linking is done */
941 static TCCSyms tcc_syms
[] = {
942 #if !defined(CONFIG_TCCBOOT)
951 void *resolve_sym(TCCState
*s1
, const char *symbol
, int type
)
955 while (p
->str
!= NULL
) {
956 if (!strcmp(p
->str
, symbol
))
963 #elif !defined(WIN32)
967 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
)
969 return dlsym(RTLD_DEFAULT
, sym
);
974 /********************************************************/
976 /* we use our own 'finite' function to avoid potential problems with
977 non standard math libs */
978 /* XXX: endianness dependent */
979 int ieee_finite(double d
)
982 return ((unsigned)((p
[1] | 0x800fffff) + 1)) >> 31;
985 /* copy a string and truncate it. */
986 static char *pstrcpy(char *buf
, int buf_size
, const char *s
)
993 q_end
= buf
+ buf_size
- 1;
1005 /* strcat and truncate. */
1006 static char *pstrcat(char *buf
, int buf_size
, const char *s
)
1011 pstrcpy(buf
+ len
, buf_size
- len
, s
);
1015 static int strstart(const char *str
, const char *val
, const char **ptr
)
1020 while (*q
!= '\0') {
1031 /* memory management */
1037 static inline void tcc_free(void *ptr
)
1040 mem_cur_size
-= malloc_usable_size(ptr
);
1045 static void *tcc_malloc(unsigned long size
)
1050 error("memory full");
1052 mem_cur_size
+= malloc_usable_size(ptr
);
1053 if (mem_cur_size
> mem_max_size
)
1054 mem_max_size
= mem_cur_size
;
1059 static void *tcc_mallocz(unsigned long size
)
1062 ptr
= tcc_malloc(size
);
1063 memset(ptr
, 0, size
);
1067 static inline void *tcc_realloc(void *ptr
, unsigned long size
)
1071 mem_cur_size
-= malloc_usable_size(ptr
);
1073 ptr1
= realloc(ptr
, size
);
1075 /* NOTE: count not correct if alloc error, but not critical */
1076 mem_cur_size
+= malloc_usable_size(ptr1
);
1077 if (mem_cur_size
> mem_max_size
)
1078 mem_max_size
= mem_cur_size
;
1083 static char *tcc_strdup(const char *str
)
1086 ptr
= tcc_malloc(strlen(str
) + 1);
1091 #define free(p) use_tcc_free(p)
1092 #define malloc(s) use_tcc_malloc(s)
1093 #define realloc(p, s) use_tcc_realloc(p, s)
1095 static void dynarray_add(void ***ptab
, int *nb_ptr
, void *data
)
1102 /* every power of two we double array size */
1103 if ((nb
& (nb
- 1)) == 0) {
1108 pp
= tcc_realloc(pp
, nb_alloc
* sizeof(void *));
1110 error("memory full");
1117 /* symbol allocator */
1118 static Sym
*__sym_malloc(void)
1120 Sym
*sym_pool
, *sym
, *last_sym
;
1123 sym_pool
= tcc_malloc(SYM_POOL_NB
* sizeof(Sym
));
1125 last_sym
= sym_free_first
;
1127 for(i
= 0; i
< SYM_POOL_NB
; i
++) {
1128 sym
->next
= last_sym
;
1132 sym_free_first
= last_sym
;
1136 static inline Sym
*sym_malloc(void)
1139 sym
= sym_free_first
;
1141 sym
= __sym_malloc();
1142 sym_free_first
= sym
->next
;
1146 static inline void sym_free(Sym
*sym
)
1148 sym
->next
= sym_free_first
;
1149 sym_free_first
= sym
;
1152 Section
*new_section(TCCState
*s1
, const char *name
, int sh_type
, int sh_flags
)
1156 sec
= tcc_mallocz(sizeof(Section
) + strlen(name
));
1157 strcpy(sec
->name
, name
);
1158 sec
->sh_type
= sh_type
;
1159 sec
->sh_flags
= sh_flags
;
1166 sec
->sh_addralign
= 4;
1169 sec
->sh_addralign
= 1;
1172 sec
->sh_addralign
= 32; /* default conservative alignment */
1176 /* only add section if not private */
1177 if (!(sh_flags
& SHF_PRIVATE
)) {
1178 sec
->sh_num
= s1
->nb_sections
;
1179 dynarray_add((void ***)&s1
->sections
, &s1
->nb_sections
, sec
);
1184 static void free_section(Section
*s
)
1190 /* realloc section and set its content to zero */
1191 static void section_realloc(Section
*sec
, unsigned long new_size
)
1194 unsigned char *data
;
1196 size
= sec
->data_allocated
;
1199 while (size
< new_size
)
1201 data
= tcc_realloc(sec
->data
, size
);
1203 error("memory full");
1204 memset(data
+ sec
->data_allocated
, 0, size
- sec
->data_allocated
);
1206 sec
->data_allocated
= size
;
1209 /* reserve at least 'size' bytes in section 'sec' from
1210 sec->data_offset. */
1211 static void *section_ptr_add(Section
*sec
, unsigned long size
)
1213 unsigned long offset
, offset1
;
1215 offset
= sec
->data_offset
;
1216 offset1
= offset
+ size
;
1217 if (offset1
> sec
->data_allocated
)
1218 section_realloc(sec
, offset1
);
1219 sec
->data_offset
= offset1
;
1220 return sec
->data
+ offset
;
1223 /* return a reference to a section, and create it if it does not
1225 Section
*find_section(TCCState
*s1
, const char *name
)
1229 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1230 sec
= s1
->sections
[i
];
1231 if (!strcmp(name
, sec
->name
))
1234 /* sections are created as PROGBITS */
1235 return new_section(s1
, name
, SHT_PROGBITS
, SHF_ALLOC
);
1238 #define SECTION_ABS ((void *)1)
1240 /* update sym->c so that it points to an external symbol in section
1241 'section' with value 'value' */
1242 static void put_extern_sym2(Sym
*sym
, Section
*section
,
1243 unsigned long value
, unsigned long size
,
1244 int can_add_underscore
)
1246 int sym_type
, sym_bind
, sh_num
, info
;
1251 if (section
== NULL
)
1253 else if (section
== SECTION_ABS
)
1256 sh_num
= section
->sh_num
;
1258 if ((sym
->type
.t
& VT_BTYPE
) == VT_FUNC
)
1259 sym_type
= STT_FUNC
;
1261 sym_type
= STT_OBJECT
;
1262 if (sym
->type
.t
& VT_STATIC
)
1263 sym_bind
= STB_LOCAL
;
1265 sym_bind
= STB_GLOBAL
;
1267 name
= get_tok_str(sym
->v
, NULL
);
1268 #ifdef CONFIG_TCC_BCHECK
1269 if (do_bounds_check
) {
1272 /* XXX: avoid doing that for statics ? */
1273 /* if bound checking is activated, we change some function
1274 names by adding the "__bound" prefix */
1277 /* XXX: we rely only on malloc hooks */
1289 strcpy(buf
, "__bound_");
1296 if (tcc_state
->leading_underscore
&& can_add_underscore
) {
1298 pstrcpy(buf1
+ 1, sizeof(buf1
) - 1, name
);
1301 info
= ELF32_ST_INFO(sym_bind
, sym_type
);
1302 sym
->c
= add_elf_sym(symtab_section
, value
, size
, info
, 0, sh_num
, name
);
1304 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
1305 esym
->st_value
= value
;
1306 esym
->st_size
= size
;
1307 esym
->st_shndx
= sh_num
;
1311 static void put_extern_sym(Sym
*sym
, Section
*section
,
1312 unsigned long value
, unsigned long size
)
1314 put_extern_sym2(sym
, section
, value
, size
, 1);
1317 /* add a new relocation entry to symbol 'sym' in section 's' */
1318 static void greloc(Section
*s
, Sym
*sym
, unsigned long offset
, int type
)
1321 put_extern_sym(sym
, NULL
, 0, 0);
1322 /* now we can add ELF relocation info */
1323 put_elf_reloc(symtab_section
, s
, offset
, type
, sym
->c
);
1326 static inline int isid(int c
)
1328 return (c
>= 'a' && c
<= 'z') ||
1329 (c
>= 'A' && c
<= 'Z') ||
1333 static inline int isnum(int c
)
1335 return c
>= '0' && c
<= '9';
1338 static inline int isoct(int c
)
1340 return c
>= '0' && c
<= '7';
1343 static inline int toup(int c
)
1345 if (c
>= 'a' && c
<= 'z')
1346 return c
- 'a' + 'A';
1351 static void strcat_vprintf(char *buf
, int buf_size
, const char *fmt
, va_list ap
)
1355 vsnprintf(buf
+ len
, buf_size
- len
, fmt
, ap
);
1358 static void strcat_printf(char *buf
, int buf_size
, const char *fmt
, ...)
1362 strcat_vprintf(buf
, buf_size
, fmt
, ap
);
1366 void error1(TCCState
*s1
, int is_warning
, const char *fmt
, va_list ap
)
1373 for(f
= s1
->include_stack
; f
< s1
->include_stack_ptr
; f
++)
1374 strcat_printf(buf
, sizeof(buf
), "In file included from %s:%d:\n",
1375 (*f
)->filename
, (*f
)->line_num
);
1376 if (file
->line_num
> 0) {
1377 strcat_printf(buf
, sizeof(buf
),
1378 "%s:%d: ", file
->filename
, file
->line_num
);
1380 strcat_printf(buf
, sizeof(buf
),
1381 "%s: ", file
->filename
);
1384 strcat_printf(buf
, sizeof(buf
),
1388 strcat_printf(buf
, sizeof(buf
), "warning: ");
1389 strcat_vprintf(buf
, sizeof(buf
), fmt
, ap
);
1391 if (!s1
->error_func
) {
1392 /* default case: stderr */
1393 fprintf(stderr
, "%s\n", buf
);
1395 s1
->error_func(s1
->error_opaque
, buf
);
1397 if (!is_warning
|| s1
->warn_error
)
1402 void tcc_set_error_func(TCCState
*s
, void *error_opaque
,
1403 void (*error_func
)(void *opaque
, const char *msg
))
1405 s
->error_opaque
= error_opaque
;
1406 s
->error_func
= error_func
;
1410 /* error without aborting current compilation */
1411 void error_noabort(const char *fmt
, ...)
1413 TCCState
*s1
= tcc_state
;
1417 error1(s1
, 0, fmt
, ap
);
1421 void error(const char *fmt
, ...)
1423 TCCState
*s1
= tcc_state
;
1427 error1(s1
, 0, fmt
, ap
);
1429 /* better than nothing: in some cases, we accept to handle errors */
1430 if (s1
->error_set_jmp_enabled
) {
1431 longjmp(s1
->error_jmp_buf
, 1);
1433 /* XXX: eliminate this someday */
1438 void expect(const char *msg
)
1440 error("%s expected", msg
);
1443 void warning(const char *fmt
, ...)
1445 TCCState
*s1
= tcc_state
;
1452 error1(s1
, 1, fmt
, ap
);
1459 error("'%c' expected", c
);
1463 static void test_lvalue(void)
1465 if (!(vtop
->r
& VT_LVAL
))
1469 /* allocate a new token */
1470 static TokenSym
*tok_alloc_new(TokenSym
**pts
, const char *str
, int len
)
1472 TokenSym
*ts
, **ptable
;
1475 if (tok_ident
>= SYM_FIRST_ANOM
)
1476 error("memory full");
1478 /* expand token table if needed */
1479 i
= tok_ident
- TOK_IDENT
;
1480 if ((i
% TOK_ALLOC_INCR
) == 0) {
1481 ptable
= tcc_realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
1483 error("memory full");
1484 table_ident
= ptable
;
1487 ts
= tcc_malloc(sizeof(TokenSym
) + len
);
1488 table_ident
[i
] = ts
;
1489 ts
->tok
= tok_ident
++;
1490 ts
->sym_define
= NULL
;
1491 ts
->sym_label
= NULL
;
1492 ts
->sym_struct
= NULL
;
1493 ts
->sym_identifier
= NULL
;
1495 ts
->hash_next
= NULL
;
1496 memcpy(ts
->str
, str
, len
);
1497 ts
->str
[len
] = '\0';
1502 #define TOK_HASH_INIT 1
1503 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1505 /* find a token and add it if not found */
1506 static TokenSym
*tok_alloc(const char *str
, int len
)
1508 TokenSym
*ts
, **pts
;
1514 h
= TOK_HASH_FUNC(h
, ((unsigned char *)str
)[i
]);
1515 h
&= (TOK_HASH_SIZE
- 1);
1517 pts
= &hash_ident
[h
];
1522 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
1524 pts
= &(ts
->hash_next
);
1526 return tok_alloc_new(pts
, str
, len
);
1529 /* CString handling */
1531 static void cstr_realloc(CString
*cstr
, int new_size
)
1536 size
= cstr
->size_allocated
;
1538 size
= 8; /* no need to allocate a too small first string */
1539 while (size
< new_size
)
1541 data
= tcc_realloc(cstr
->data_allocated
, size
);
1543 error("memory full");
1544 cstr
->data_allocated
= data
;
1545 cstr
->size_allocated
= size
;
1550 static inline void cstr_ccat(CString
*cstr
, int ch
)
1553 size
= cstr
->size
+ 1;
1554 if (size
> cstr
->size_allocated
)
1555 cstr_realloc(cstr
, size
);
1556 ((unsigned char *)cstr
->data
)[size
- 1] = ch
;
1560 static void cstr_cat(CString
*cstr
, const char *str
)
1572 /* add a wide char */
1573 static void cstr_wccat(CString
*cstr
, int ch
)
1576 size
= cstr
->size
+ sizeof(nwchar_t
);
1577 if (size
> cstr
->size_allocated
)
1578 cstr_realloc(cstr
, size
);
1579 *(nwchar_t
*)(((unsigned char *)cstr
->data
) + size
- sizeof(nwchar_t
)) = ch
;
1583 static void cstr_new(CString
*cstr
)
1585 memset(cstr
, 0, sizeof(CString
));
1588 /* free string and reset it to NULL */
1589 static void cstr_free(CString
*cstr
)
1591 tcc_free(cstr
->data_allocated
);
1595 #define cstr_reset(cstr) cstr_free(cstr)
1597 /* XXX: unicode ? */
1598 static void add_char(CString
*cstr
, int c
)
1600 if (c
== '\'' || c
== '\"' || c
== '\\') {
1601 /* XXX: could be more precise if char or string */
1602 cstr_ccat(cstr
, '\\');
1604 if (c
>= 32 && c
<= 126) {
1607 cstr_ccat(cstr
, '\\');
1609 cstr_ccat(cstr
, 'n');
1611 cstr_ccat(cstr
, '0' + ((c
>> 6) & 7));
1612 cstr_ccat(cstr
, '0' + ((c
>> 3) & 7));
1613 cstr_ccat(cstr
, '0' + (c
& 7));
1618 /* XXX: buffer overflow */
1619 /* XXX: float tokens */
1620 char *get_tok_str(int v
, CValue
*cv
)
1622 static char buf
[STRING_MAX_SIZE
+ 1];
1623 static CString cstr_buf
;
1629 /* NOTE: to go faster, we give a fixed buffer for small strings */
1630 cstr_reset(&cstr_buf
);
1631 cstr_buf
.data
= buf
;
1632 cstr_buf
.size_allocated
= sizeof(buf
);
1638 /* XXX: not quite exact, but only useful for testing */
1639 sprintf(p
, "%u", cv
->ui
);
1643 /* XXX: not quite exact, but only useful for testing */
1644 sprintf(p
, "%Lu", cv
->ull
);
1648 cstr_ccat(&cstr_buf
, '\'');
1649 add_char(&cstr_buf
, cv
->i
);
1650 cstr_ccat(&cstr_buf
, '\'');
1651 cstr_ccat(&cstr_buf
, '\0');
1655 len
= cstr
->size
- 1;
1657 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1658 cstr_ccat(&cstr_buf
, '\0');
1663 cstr_ccat(&cstr_buf
, '\"');
1665 len
= cstr
->size
- 1;
1667 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1669 len
= (cstr
->size
/ sizeof(nwchar_t
)) - 1;
1671 add_char(&cstr_buf
, ((nwchar_t
*)cstr
->data
)[i
]);
1673 cstr_ccat(&cstr_buf
, '\"');
1674 cstr_ccat(&cstr_buf
, '\0');
1683 return strcpy(p
, "...");
1685 return strcpy(p
, "<<=");
1687 return strcpy(p
, ">>=");
1689 if (v
< TOK_IDENT
) {
1690 /* search in two bytes table */
1704 } else if (v
< tok_ident
) {
1705 return table_ident
[v
- TOK_IDENT
]->str
;
1706 } else if (v
>= SYM_FIRST_ANOM
) {
1707 /* special name for anonymous symbol */
1708 sprintf(p
, "L.%u", v
- SYM_FIRST_ANOM
);
1710 /* should never happen */
1715 return cstr_buf
.data
;
1718 /* push, without hashing */
1719 static Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
1733 /* find a symbol and return its associated structure. 's' is the top
1734 of the symbol stack */
1735 static Sym
*sym_find2(Sym
*s
, int v
)
1745 /* structure lookup */
1746 static inline Sym
*struct_find(int v
)
1749 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1751 return table_ident
[v
]->sym_struct
;
1754 /* find an identifier */
1755 static inline Sym
*sym_find(int v
)
1758 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1760 return table_ident
[v
]->sym_identifier
;
1763 /* push a given symbol on the symbol stack */
1764 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
)
1773 s
= sym_push2(ps
, v
, type
->t
, c
);
1774 s
->type
.ref
= type
->ref
;
1776 /* don't record fields or anonymous symbols */
1778 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1779 /* record symbol in token array */
1780 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1782 ps
= &ts
->sym_struct
;
1784 ps
= &ts
->sym_identifier
;
1791 /* push a global identifier */
1792 static Sym
*global_identifier_push(int v
, int t
, int c
)
1795 s
= sym_push2(&global_stack
, v
, t
, c
);
1796 /* don't record anonymous symbol */
1797 if (v
< SYM_FIRST_ANOM
) {
1798 ps
= &table_ident
[v
- TOK_IDENT
]->sym_identifier
;
1799 /* modify the top most local identifier, so that
1800 sym_identifier will point to 's' when popped */
1802 ps
= &(*ps
)->prev_tok
;
1809 /* pop symbols until top reaches 'b' */
1810 static void sym_pop(Sym
**ptop
, Sym
*b
)
1820 /* remove symbol in token array */
1822 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1823 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1825 ps
= &ts
->sym_struct
;
1827 ps
= &ts
->sym_identifier
;
1838 BufferedFile
*tcc_open(TCCState
*s1
, const char *filename
)
1844 fd
= open(filename
, O_RDONLY
| O_BINARY
);
1847 bf
= tcc_malloc(sizeof(BufferedFile
));
1853 bf
->buf_ptr
= bf
->buffer
;
1854 bf
->buf_end
= bf
->buffer
;
1855 bf
->buffer
[0] = CH_EOB
; /* put eob symbol */
1856 pstrcpy(bf
->filename
, sizeof(bf
->filename
), filename
);
1857 len
= strlen(bf
->filename
);
1858 for (i
= 0; i
< len
; i
++)
1859 if (bf
->filename
[i
] == '\\')
1860 bf
->filename
[i
] = '/';
1862 bf
->ifndef_macro
= 0;
1863 bf
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
1864 // printf("opening '%s'\n", filename);
1868 void tcc_close(BufferedFile
*bf
)
1870 total_lines
+= bf
->line_num
;
1875 /* fill input buffer and peek next char */
1876 static int tcc_peekc_slow(BufferedFile
*bf
)
1879 /* only tries to read if really end of buffer */
1880 if (bf
->buf_ptr
>= bf
->buf_end
) {
1882 #if defined(PARSE_DEBUG)
1887 len
= read(bf
->fd
, bf
->buffer
, len
);
1894 bf
->buf_ptr
= bf
->buffer
;
1895 bf
->buf_end
= bf
->buffer
+ len
;
1896 *bf
->buf_end
= CH_EOB
;
1898 if (bf
->buf_ptr
< bf
->buf_end
) {
1899 return bf
->buf_ptr
[0];
1901 bf
->buf_ptr
= bf
->buf_end
;
1906 /* return the current character, handling end of block if necessary
1908 static int handle_eob(void)
1910 return tcc_peekc_slow(file
);
1913 /* read next char from current input file and handle end of input buffer */
1914 static inline void inp(void)
1916 ch
= *(++(file
->buf_ptr
));
1917 /* end of buffer/file handling */
1922 /* handle '\[\r]\n' */
1923 static void handle_stray(void)
1925 while (ch
== '\\') {
1930 } else if (ch
== '\r') {
1938 error("stray '\\' in program");
1943 /* skip the stray and handle the \\n case. Output an error if
1944 incorrect char after the stray */
1945 static int handle_stray1(uint8_t *p
)
1949 if (p
>= file
->buf_end
) {
1966 /* handle just the EOB case, but not stray */
1967 #define PEEKC_EOB(c, p)\
1978 /* handle the complicated stray case */
1979 #define PEEKC(c, p)\
1984 c = handle_stray1(p);\
1989 /* input with '\[\r]\n' handling. Note that this function cannot
1990 handle other characters after '\', so you cannot call it inside
1991 strings or comments */
1992 static void minp(void)
2000 /* single line C++ comments */
2001 static uint8_t *parse_line_comment(uint8_t *p
)
2009 if (c
== '\n' || c
== CH_EOF
) {
2011 } else if (c
== '\\') {
2020 } else if (c
== '\r') {
2038 static uint8_t *parse_comment(uint8_t *p
)
2044 /* fast skip loop */
2047 if (c
== '\n' || c
== '*' || c
== '\\')
2051 if (c
== '\n' || c
== '*' || c
== '\\')
2055 /* now we can handle all the cases */
2059 } else if (c
== '*') {
2065 } else if (c
== '/') {
2066 goto end_of_comment
;
2067 } else if (c
== '\\') {
2072 /* skip '\[\r]\n', otherwise just skip the stray */
2078 } else if (c
== '\r') {
2095 /* stray, eob or eof */
2100 error("unexpected end of file in comment");
2101 } else if (c
== '\\') {
2113 /* space exlcuding newline */
2114 static inline int is_space(int ch
)
2116 return ch
== ' ' || ch
== '\t' || ch
== '\v' || ch
== '\f' || ch
== '\r';
2119 static inline void skip_spaces(void)
2121 while (is_space(ch
))
2125 /* parse a string without interpreting escapes */
2126 static uint8_t *parse_pp_string(uint8_t *p
,
2127 int sep
, CString
*str
)
2135 } else if (c
== '\\') {
2140 unterminated_string
:
2141 /* XXX: indicate line number of start of string */
2142 error("missing terminating %c character", sep
);
2143 } else if (c
== '\\') {
2144 /* escape : just skip \[\r]\n */
2149 } else if (c
== '\r') {
2152 expect("'\n' after '\r'");
2155 } else if (c
== CH_EOF
) {
2156 goto unterminated_string
;
2159 cstr_ccat(str
, '\\');
2165 } else if (c
== '\n') {
2168 } else if (c
== '\r') {
2172 cstr_ccat(str
, '\r');
2188 /* skip block of text until #else, #elif or #endif. skip also pairs of
2190 void preprocess_skip(void)
2192 int a
, start_of_line
, c
;
2219 } else if (c
== '\\') {
2220 /* XXX: incorrect: should not give an error */
2221 ch
= file
->buf_ptr
[0];
2229 p
= parse_pp_string(p
, c
, NULL
);
2238 p
= parse_comment(p
);
2239 } else if (ch
== '/') {
2240 p
= parse_line_comment(p
);
2246 if (start_of_line
) {
2251 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
2253 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
2255 else if (tok
== TOK_ENDIF
)
2269 /* ParseState handling */
2271 /* XXX: currently, no include file info is stored. Thus, we cannot display
2272 accurate messages if the function or data definition spans multiple
2275 /* save current parse state in 's' */
2276 void save_parse_state(ParseState
*s
)
2278 s
->line_num
= file
->line_num
;
2279 s
->macro_ptr
= macro_ptr
;
2284 /* restore parse state from 's' */
2285 void restore_parse_state(ParseState
*s
)
2287 file
->line_num
= s
->line_num
;
2288 macro_ptr
= s
->macro_ptr
;
2293 /* return the number of additional 'ints' necessary to store the
2295 static inline int tok_ext_size(int t
)
2309 error("unsupported token");
2316 return LDOUBLE_SIZE
/ 4;
2322 /* token string handling */
2324 static inline void tok_str_new(TokenString
*s
)
2328 s
->allocated_len
= 0;
2329 s
->last_line_num
= -1;
2332 static void tok_str_free(int *str
)
2337 static int *tok_str_realloc(TokenString
*s
)
2341 if (s
->allocated_len
== 0) {
2344 len
= s
->allocated_len
* 2;
2346 str
= tcc_realloc(s
->str
, len
* sizeof(int));
2348 error("memory full");
2349 s
->allocated_len
= len
;
2354 static void tok_str_add(TokenString
*s
, int t
)
2360 if (len
>= s
->allocated_len
)
2361 str
= tok_str_realloc(s
);
2366 static void tok_str_add2(TokenString
*s
, int t
, CValue
*cv
)
2373 /* allocate space for worst case */
2374 if (len
+ TOK_MAX_SIZE
> s
->allocated_len
)
2375 str
= tok_str_realloc(s
);
2384 str
[len
++] = cv
->tab
[0];
2393 nb_words
= (sizeof(CString
) + cv
->cstr
->size
+ 3) >> 2;
2394 while ((len
+ nb_words
) > s
->allocated_len
)
2395 str
= tok_str_realloc(s
);
2396 cstr
= (CString
*)(str
+ len
);
2398 cstr
->size
= cv
->cstr
->size
;
2399 cstr
->data_allocated
= NULL
;
2400 cstr
->size_allocated
= cstr
->size
;
2401 memcpy((char *)cstr
+ sizeof(CString
),
2402 cv
->cstr
->data
, cstr
->size
);
2409 #if LDOUBLE_SIZE == 8
2412 str
[len
++] = cv
->tab
[0];
2413 str
[len
++] = cv
->tab
[1];
2415 #if LDOUBLE_SIZE == 12
2417 str
[len
++] = cv
->tab
[0];
2418 str
[len
++] = cv
->tab
[1];
2419 str
[len
++] = cv
->tab
[2];
2420 #elif LDOUBLE_SIZE != 8
2421 #error add long double size support
2430 /* add the current parse token in token string 's' */
2431 static void tok_str_add_tok(TokenString
*s
)
2435 /* save line number info */
2436 if (file
->line_num
!= s
->last_line_num
) {
2437 s
->last_line_num
= file
->line_num
;
2438 cval
.i
= s
->last_line_num
;
2439 tok_str_add2(s
, TOK_LINENUM
, &cval
);
2441 tok_str_add2(s
, tok
, &tokc
);
2444 #if LDOUBLE_SIZE == 12
2445 #define LDOUBLE_GET(p, cv) \
2449 #elif LDOUBLE_SIZE == 8
2450 #define LDOUBLE_GET(p, cv) \
2454 #error add long double size support
2458 /* get a token from an integer array and increment pointer
2459 accordingly. we code it as a macro to avoid pointer aliasing. */
2460 #define TOK_GET(t, p, cv) \
2475 cv.cstr = (CString *)p; \
2476 cv.cstr->data = (char *)p + sizeof(CString);\
2477 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2486 case TOK_CLDOUBLE: \
2487 LDOUBLE_GET(p, cv); \
2488 p += LDOUBLE_SIZE / 4; \
2495 /* defines handling */
2496 static inline void define_push(int v
, int macro_type
, int *str
, Sym
*first_arg
)
2500 s
= sym_push2(&define_stack
, v
, macro_type
, (int)str
);
2501 s
->next
= first_arg
;
2502 table_ident
[v
- TOK_IDENT
]->sym_define
= s
;
2505 /* undefined a define symbol. Its name is just set to zero */
2506 static void define_undef(Sym
*s
)
2510 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2511 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2515 static inline Sym
*define_find(int v
)
2518 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2520 return table_ident
[v
]->sym_define
;
2523 /* free define stack until top reaches 'b' */
2524 static void free_defines(Sym
*b
)
2532 /* do not free args or predefined defines */
2534 tok_str_free((int *)top
->c
);
2536 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2537 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2545 static Sym
*label_find(int v
)
2548 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2550 return table_ident
[v
]->sym_label
;
2553 static Sym
*label_push(Sym
**ptop
, int v
, int flags
)
2556 s
= sym_push2(ptop
, v
, 0, 0);
2558 ps
= &table_ident
[v
- TOK_IDENT
]->sym_label
;
2559 if (ptop
== &global_label_stack
) {
2560 /* modify the top most local identifier, so that
2561 sym_identifier will point to 's' when popped */
2563 ps
= &(*ps
)->prev_tok
;
2570 /* pop labels until element last is reached. Look if any labels are
2571 undefined. Define symbols if '&&label' was used. */
2572 static void label_pop(Sym
**ptop
, Sym
*slast
)
2575 for(s
= *ptop
; s
!= slast
; s
= s1
) {
2577 if (s
->r
== LABEL_DECLARED
) {
2578 warning("label '%s' declared but not used", get_tok_str(s
->v
, NULL
));
2579 } else if (s
->r
== LABEL_FORWARD
) {
2580 error("label '%s' used but not defined",
2581 get_tok_str(s
->v
, NULL
));
2584 /* define corresponding symbol. A size of
2586 put_extern_sym(s
, cur_text_section
, (long)s
->next
, 1);
2590 table_ident
[s
->v
- TOK_IDENT
]->sym_label
= s
->prev_tok
;
2596 /* eval an expression for #if/#elif */
2597 static int expr_preprocess(void)
2603 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2604 next(); /* do macro subst */
2605 if (tok
== TOK_DEFINED
) {
2610 c
= define_find(tok
) != 0;
2615 } else if (tok
>= TOK_IDENT
) {
2616 /* if undefined macro */
2620 tok_str_add_tok(&str
);
2622 tok_str_add(&str
, -1); /* simulate end of file */
2623 tok_str_add(&str
, 0);
2624 /* now evaluate C constant expression */
2625 macro_ptr
= str
.str
;
2629 tok_str_free(str
.str
);
2633 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2634 static void tok_print(int *str
)
2640 TOK_GET(t
, str
, cval
);
2643 printf(" %s", get_tok_str(t
, &cval
));
2649 /* parse after #define */
2650 static void parse_define(void)
2652 Sym
*s
, *first
, **ps
;
2653 int v
, t
, varg
, is_vaargs
, c
;
2658 error("invalid macro name '%s'", get_tok_str(tok
, &tokc
));
2659 /* XXX: should check if same macro (ANSI) */
2662 /* '(' must be just after macro definition for MACRO_FUNC */
2663 c
= file
->buf_ptr
[0];
2665 c
= handle_stray1(file
->buf_ptr
);
2670 while (tok
!= ')') {
2674 if (varg
== TOK_DOTS
) {
2675 varg
= TOK___VA_ARGS__
;
2677 } else if (tok
== TOK_DOTS
&& gnu_ext
) {
2681 if (varg
< TOK_IDENT
)
2682 error("badly punctuated parameter list");
2683 s
= sym_push2(&define_stack
, varg
| SYM_FIELD
, is_vaargs
, 0);
2694 /* EOF testing necessary for '-D' handling */
2695 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2696 tok_str_add2(&str
, tok
, &tokc
);
2699 tok_str_add(&str
, 0);
2701 printf("define %s %d: ", get_tok_str(v
, NULL
), t
);
2704 define_push(v
, t
, str
.str
, first
);
2707 static inline int hash_cached_include(int type
, const char *filename
)
2709 const unsigned char *s
;
2713 h
= TOK_HASH_FUNC(h
, type
);
2716 h
= TOK_HASH_FUNC(h
, *s
);
2719 h
&= (CACHED_INCLUDES_HASH_SIZE
- 1);
2723 /* XXX: use a token or a hash table to accelerate matching ? */
2724 static CachedInclude
*search_cached_include(TCCState
*s1
,
2725 int type
, const char *filename
)
2729 h
= hash_cached_include(type
, filename
);
2730 i
= s1
->cached_includes_hash
[h
];
2734 e
= s1
->cached_includes
[i
- 1];
2735 if (e
->type
== type
&& !strcmp(e
->filename
, filename
))
2742 static inline void add_cached_include(TCCState
*s1
, int type
,
2743 const char *filename
, int ifndef_macro
)
2748 if (search_cached_include(s1
, type
, filename
))
2751 printf("adding cached '%s' %s\n", filename
, get_tok_str(ifndef_macro
, NULL
));
2753 e
= tcc_malloc(sizeof(CachedInclude
) + strlen(filename
));
2757 strcpy(e
->filename
, filename
);
2758 e
->ifndef_macro
= ifndef_macro
;
2759 dynarray_add((void ***)&s1
->cached_includes
, &s1
->nb_cached_includes
, e
);
2760 /* add in hash table */
2761 h
= hash_cached_include(type
, filename
);
2762 e
->hash_next
= s1
->cached_includes_hash
[h
];
2763 s1
->cached_includes_hash
[h
] = s1
->nb_cached_includes
;
2766 static void pragma_parse(TCCState
*s1
)
2771 if (tok
== TOK_pack
) {
2774 #pragma pack(1) // set
2775 #pragma pack() // reset to default
2776 #pragma pack(push,1) // push & set
2777 #pragma pack(pop) // restore previous
2781 if (tok
== TOK_ASM_pop
) {
2783 if (s1
->pack_stack_ptr
<= s1
->pack_stack
) {
2785 error("out of pack stack");
2787 s1
->pack_stack_ptr
--;
2791 if (tok
== TOK_ASM_push
) {
2793 if (s1
->pack_stack_ptr
>= s1
->pack_stack
+ PACK_STACK_SIZE
- 1)
2795 s1
->pack_stack_ptr
++;
2798 if (tok
!= TOK_CINT
) {
2800 error("invalid pack pragma");
2803 if (val
< 1 || val
> 16 || (val
& (val
- 1)) != 0)
2807 *s1
->pack_stack_ptr
= val
;
2813 /* is_bof is true if first non space token at beginning of file */
2814 static void preprocess(int is_bof
)
2816 TCCState
*s1
= tcc_state
;
2817 int size
, i
, c
, n
, saved_parse_flags
;
2818 char buf
[1024], *q
, *p
;
2824 saved_parse_flags
= parse_flags
;
2825 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
|
2826 PARSE_FLAG_LINEFEED
;
2836 s
= define_find(tok
);
2837 /* undefine symbol by putting an invalid name */
2842 case TOK_INCLUDE_NEXT
:
2843 ch
= file
->buf_ptr
[0];
2844 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2849 } else if (ch
== '\"') {
2852 /* XXX: better stray handling */
2855 while (ch
!= c
&& ch
!= '\n' && ch
!= CH_EOF
) {
2856 if ((q
- buf
) < sizeof(buf
) - 1)
2863 /* eat all spaces and comments after include */
2864 /* XXX: slightly incorrect */
2865 while (ch1
!= '\n' && ch1
!= CH_EOF
)
2869 /* computed #include : either we have only strings or
2870 we have anything enclosed in '<>' */
2873 if (tok
== TOK_STR
) {
2874 while (tok
!= TOK_LINEFEED
) {
2875 if (tok
!= TOK_STR
) {
2877 error("'#include' expects \"FILENAME\" or <FILENAME>");
2879 pstrcat(buf
, sizeof(buf
), (char *)tokc
.cstr
->data
);
2885 while (tok
!= TOK_LINEFEED
) {
2886 pstrcat(buf
, sizeof(buf
), get_tok_str(tok
, &tokc
));
2890 /* check syntax and remove '<>' */
2891 if (len
< 2 || buf
[0] != '<' || buf
[len
- 1] != '>')
2892 goto include_syntax
;
2893 memmove(buf
, buf
+ 1, len
- 2);
2894 buf
[len
- 2] = '\0';
2899 e
= search_cached_include(s1
, c
, buf
);
2900 if (e
&& define_find(e
->ifndef_macro
)) {
2901 /* no need to parse the include because the 'ifndef macro'
2904 printf("%s: skipping %s\n", file
->filename
, buf
);
2908 /* first search in current dir if "header.h" */
2910 p
= strrchr(file
->filename
, '/');
2912 size
= p
+ 1 - file
->filename
;
2913 if (size
> sizeof(buf1
) - 1)
2914 size
= sizeof(buf1
) - 1;
2915 memcpy(buf1
, file
->filename
, size
);
2917 pstrcat(buf1
, sizeof(buf1
), buf
);
2918 f
= tcc_open(s1
, buf1
);
2920 if (tok
== TOK_INCLUDE_NEXT
)
2926 if (s1
->include_stack_ptr
>= s1
->include_stack
+ INCLUDE_STACK_SIZE
)
2927 error("#include recursion too deep");
2928 /* now search in all the include paths */
2929 n
= s1
->nb_include_paths
+ s1
->nb_sysinclude_paths
;
2930 for(i
= 0; i
< n
; i
++) {
2932 if (i
< s1
->nb_include_paths
)
2933 path
= s1
->include_paths
[i
];
2935 path
= s1
->sysinclude_paths
[i
- s1
->nb_include_paths
];
2936 pstrcpy(buf1
, sizeof(buf1
), path
);
2937 pstrcat(buf1
, sizeof(buf1
), "/");
2938 pstrcat(buf1
, sizeof(buf1
), buf
);
2939 f
= tcc_open(s1
, buf1
);
2941 if (tok
== TOK_INCLUDE_NEXT
)
2947 error("include file '%s' not found", buf
);
2951 printf("%s: including %s\n", file
->filename
, buf1
);
2954 pstrcpy(f
->inc_filename
, sizeof(f
->inc_filename
), buf
);
2955 /* push current file in stack */
2956 /* XXX: fix current line init */
2957 *s1
->include_stack_ptr
++ = file
;
2959 /* add include file debug info */
2961 put_stabs(file
->filename
, N_BINCL
, 0, 0, 0);
2963 tok_flags
|= TOK_FLAG_BOF
| TOK_FLAG_BOL
;
2964 ch
= file
->buf_ptr
[0];
2972 c
= expr_preprocess();
2978 if (tok
< TOK_IDENT
)
2979 error("invalid argument for '#if%sdef'", c
? "n" : "");
2983 printf("#ifndef %s\n", get_tok_str(tok
, NULL
));
2985 file
->ifndef_macro
= tok
;
2988 c
= (define_find(tok
) != 0) ^ c
;
2990 if (s1
->ifdef_stack_ptr
>= s1
->ifdef_stack
+ IFDEF_STACK_SIZE
)
2991 error("memory full");
2992 *s1
->ifdef_stack_ptr
++ = c
;
2995 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
2996 error("#else without matching #if");
2997 if (s1
->ifdef_stack_ptr
[-1] & 2)
2998 error("#else after #else");
2999 c
= (s1
->ifdef_stack_ptr
[-1] ^= 3);
3002 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
3003 error("#elif without matching #if");
3004 c
= s1
->ifdef_stack_ptr
[-1];
3006 error("#elif after #else");
3007 /* last #if/#elif expression was true: we skip */
3010 c
= expr_preprocess();
3011 s1
->ifdef_stack_ptr
[-1] = c
;
3021 if (s1
->ifdef_stack_ptr
<= file
->ifdef_stack_ptr
)
3022 error("#endif without matching #if");
3023 s1
->ifdef_stack_ptr
--;
3024 /* '#ifndef macro' was at the start of file. Now we check if
3025 an '#endif' is exactly at the end of file */
3026 if (file
->ifndef_macro
&&
3027 s1
->ifdef_stack_ptr
== file
->ifdef_stack_ptr
) {
3028 file
->ifndef_macro_saved
= file
->ifndef_macro
;
3029 /* need to set to zero to avoid false matches if another
3030 #ifndef at middle of file */
3031 file
->ifndef_macro
= 0;
3032 while (tok
!= TOK_LINEFEED
)
3034 tok_flags
|= TOK_FLAG_ENDIF
;
3040 if (tok
!= TOK_CINT
)
3042 file
->line_num
= tokc
.i
- 1; /* the line number will be incremented after */
3044 if (tok
!= TOK_LINEFEED
) {
3047 pstrcpy(file
->filename
, sizeof(file
->filename
),
3048 (char *)tokc
.cstr
->data
);
3054 ch
= file
->buf_ptr
[0];
3057 while (ch
!= '\n' && ch
!= CH_EOF
) {
3058 if ((q
- buf
) < sizeof(buf
) - 1)
3064 error("#error %s", buf
);
3066 warning("#warning %s", buf
);
3072 if (tok
== TOK_LINEFEED
|| tok
== '!' || tok
== TOK_CINT
) {
3073 /* '!' is ignored to allow C scripts. numbers are ignored
3074 to emulate cpp behaviour */
3076 if (!(saved_parse_flags
& PARSE_FLAG_ASM_COMMENTS
))
3077 error("invalid preprocessing directive #%s", get_tok_str(tok
, &tokc
));
3081 /* ignore other preprocess commands or #! for C scripts */
3082 while (tok
!= TOK_LINEFEED
)
3085 parse_flags
= saved_parse_flags
;
3088 /* evaluate escape codes in a string. */
3089 static void parse_escape_string(CString
*outstr
, const uint8_t *buf
, int is_long
)
3104 case '0': case '1': case '2': case '3':
3105 case '4': case '5': case '6': case '7':
3106 /* at most three octal digits */
3111 n
= n
* 8 + c
- '0';
3115 n
= n
* 8 + c
- '0';
3120 goto add_char_nonext
;
3126 if (c
>= 'a' && c
<= 'f')
3128 else if (c
>= 'A' && c
<= 'F')
3138 goto add_char_nonext
;
3162 goto invalid_escape
;
3172 if (c
>= '!' && c
<= '~')
3173 warning("unknown escape sequence: \'\\%c\'", c
);
3175 warning("unknown escape sequence: \'\\x%x\'", c
);
3182 cstr_ccat(outstr
, c
);
3184 cstr_wccat(outstr
, c
);
3186 /* add a trailing '\0' */
3188 cstr_ccat(outstr
, '\0');
3190 cstr_wccat(outstr
, '\0');
3193 /* we use 64 bit numbers */
3196 /* bn = (bn << shift) | or_val */
3197 void bn_lshift(unsigned int *bn
, int shift
, int or_val
)
3201 for(i
=0;i
<BN_SIZE
;i
++) {
3203 bn
[i
] = (v
<< shift
) | or_val
;
3204 or_val
= v
>> (32 - shift
);
3208 void bn_zero(unsigned int *bn
)
3211 for(i
=0;i
<BN_SIZE
;i
++) {
3216 /* parse number in null terminated string 'p' and return it in the
3218 void parse_number(const char *p
)
3220 int b
, t
, shift
, frac_bits
, s
, exp_val
, ch
;
3222 unsigned int bn
[BN_SIZE
];
3233 goto float_frac_parse
;
3234 } else if (t
== '0') {
3235 if (ch
== 'x' || ch
== 'X') {
3239 } else if (tcc_ext
&& (ch
== 'b' || ch
== 'B')) {
3245 /* parse all digits. cannot check octal numbers at this stage
3246 because of floating point constants */
3248 if (ch
>= 'a' && ch
<= 'f')
3250 else if (ch
>= 'A' && ch
<= 'F')
3258 if (q
>= token_buf
+ STRING_MAX_SIZE
) {
3260 error("number too long");
3266 ((ch
== 'e' || ch
== 'E') && b
== 10) ||
3267 ((ch
== 'p' || ch
== 'P') && (b
== 16 || b
== 2))) {
3269 /* NOTE: strtox should support that for hexa numbers, but
3270 non ISOC99 libcs do not support it, so we prefer to do
3272 /* hexadecimal or binary floats */
3273 /* XXX: handle overflows */
3285 } else if (t
>= 'a') {
3287 } else if (t
>= 'A') {
3292 bn_lshift(bn
, shift
, t
);
3299 if (t
>= 'a' && t
<= 'f') {
3301 } else if (t
>= 'A' && t
<= 'F') {
3303 } else if (t
>= '0' && t
<= '9') {
3309 error("invalid digit");
3310 bn_lshift(bn
, shift
, t
);
3315 if (ch
!= 'p' && ch
!= 'P')
3322 } else if (ch
== '-') {
3326 if (ch
< '0' || ch
> '9')
3327 expect("exponent digits");
3328 while (ch
>= '0' && ch
<= '9') {
3329 exp_val
= exp_val
* 10 + ch
- '0';
3332 exp_val
= exp_val
* s
;
3334 /* now we can generate the number */
3335 /* XXX: should patch directly float number */
3336 d
= (double)bn
[1] * 4294967296.0 + (double)bn
[0];
3337 d
= ldexp(d
, exp_val
- frac_bits
);
3342 /* float : should handle overflow */
3344 } else if (t
== 'L') {
3347 /* XXX: not large enough */
3348 tokc
.ld
= (long double)d
;
3354 /* decimal floats */
3356 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3361 while (ch
>= '0' && ch
<= '9') {
3362 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3368 if (ch
== 'e' || ch
== 'E') {
3369 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3373 if (ch
== '-' || ch
== '+') {
3374 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3379 if (ch
< '0' || ch
> '9')
3380 expect("exponent digits");
3381 while (ch
>= '0' && ch
<= '9') {
3382 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3394 tokc
.f
= strtof(token_buf
, NULL
);
3395 } else if (t
== 'L') {
3398 tokc
.ld
= strtold(token_buf
, NULL
);
3401 tokc
.d
= strtod(token_buf
, NULL
);
3405 unsigned long long n
, n1
;
3408 /* integer number */
3411 if (b
== 10 && *q
== '0') {
3418 /* no need for checks except for base 10 / 8 errors */
3421 } else if (t
>= 'a') {
3423 } else if (t
>= 'A') {
3428 error("invalid digit");
3432 /* detect overflow */
3433 /* XXX: this test is not reliable */
3435 error("integer constant overflow");
3438 /* XXX: not exactly ANSI compliant */
3439 if ((n
& 0xffffffff00000000LL
) != 0) {
3444 } else if (n
> 0x7fffffff) {
3455 error("three 'l's in integer constant");
3458 if (tok
== TOK_CINT
)
3460 else if (tok
== TOK_CUINT
)
3464 } else if (t
== 'U') {
3466 error("two 'u's in integer constant");
3468 if (tok
== TOK_CINT
)
3470 else if (tok
== TOK_CLLONG
)
3477 if (tok
== TOK_CINT
|| tok
== TOK_CUINT
)
3485 #define PARSE2(c1, tok1, c2, tok2) \
3496 /* return next token without macro substitution */
3497 static inline void next_nomacro1(void)
3517 /* first look if it is in fact an end of buffer */
3518 if (p
>= file
->buf_end
) {
3522 if (p
>= file
->buf_end
)
3535 TCCState
*s1
= tcc_state
;
3536 if (parse_flags
& PARSE_FLAG_LINEFEED
) {
3538 } else if (s1
->include_stack_ptr
== s1
->include_stack
||
3539 !(parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3540 /* no include left : end of file. */
3543 /* pop include file */
3545 /* test if previous '#endif' was after a #ifdef at
3547 if (tok_flags
& TOK_FLAG_ENDIF
) {
3549 printf("#endif %s\n", get_tok_str(file
->ifndef_macro_saved
, NULL
));
3551 add_cached_include(s1
, file
->inc_type
, file
->inc_filename
,
3552 file
->ifndef_macro_saved
);
3555 /* add end of include file debug info */
3557 put_stabd(N_EINCL
, 0, 0);
3559 /* pop include stack */
3561 s1
->include_stack_ptr
--;
3562 file
= *s1
->include_stack_ptr
;
3570 if (parse_flags
& PARSE_FLAG_LINEFEED
) {
3574 tok_flags
|= TOK_FLAG_BOL
;
3583 if ((tok_flags
& TOK_FLAG_BOL
) &&
3584 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3586 preprocess(tok_flags
& TOK_FLAG_BOF
);
3592 tok
= TOK_TWOSHARPS
;
3594 if (parse_flags
& PARSE_FLAG_ASM_COMMENTS
) {
3595 p
= parse_line_comment(p
- 1);
3604 case 'a': case 'b': case 'c': case 'd':
3605 case 'e': case 'f': case 'g': case 'h':
3606 case 'i': case 'j': case 'k': case 'l':
3607 case 'm': case 'n': case 'o': case 'p':
3608 case 'q': case 'r': case 's': case 't':
3609 case 'u': case 'v': case 'w': case 'x':
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':
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':
3622 h
= TOK_HASH_FUNC(h
, c
);
3626 if (!isidnum_table
[c
])
3628 h
= TOK_HASH_FUNC(h
, c
);
3635 /* fast case : no stray found, so we have the full token
3636 and we have already hashed it */
3638 h
&= (TOK_HASH_SIZE
- 1);
3639 pts
= &hash_ident
[h
];
3644 if (ts
->len
== len
&& !memcmp(ts
->str
, p1
, len
))
3646 pts
= &(ts
->hash_next
);
3648 ts
= tok_alloc_new(pts
, p1
, len
);
3652 cstr_reset(&tokcstr
);
3655 cstr_ccat(&tokcstr
, *p1
);
3661 while (isidnum_table
[c
]) {
3662 cstr_ccat(&tokcstr
, c
);
3665 ts
= tok_alloc(tokcstr
.data
, tokcstr
.size
);
3671 if (t
!= '\\' && t
!= '\'' && t
!= '\"') {
3673 goto parse_ident_fast
;
3676 if (c
== '\'' || c
== '\"') {
3680 cstr_reset(&tokcstr
);
3681 cstr_ccat(&tokcstr
, 'L');
3682 goto parse_ident_slow
;
3686 case '0': case '1': case '2': case '3':
3687 case '4': case '5': case '6': case '7':
3690 cstr_reset(&tokcstr
);
3691 /* after the first digit, accept digits, alpha, '.' or sign if
3692 prefixed by 'eEpP' */
3696 cstr_ccat(&tokcstr
, c
);
3698 if (!(isnum(c
) || isid(c
) || c
== '.' ||
3699 ((c
== '+' || c
== '-') &&
3700 (t
== 'e' || t
== 'E' || t
== 'p' || t
== 'P'))))
3703 /* We add a trailing '\0' to ease parsing */
3704 cstr_ccat(&tokcstr
, '\0');
3705 tokc
.cstr
= &tokcstr
;
3709 /* special dot handling because it can also start a number */
3712 cstr_reset(&tokcstr
);
3713 cstr_ccat(&tokcstr
, '.');
3715 } else if (c
== '.') {
3735 /* parse the string */
3737 p
= parse_pp_string(p
, sep
, &str
);
3738 cstr_ccat(&str
, '\0');
3740 /* eval the escape (should be done as TOK_PPNUM) */
3741 cstr_reset(&tokcstr
);
3742 parse_escape_string(&tokcstr
, str
.data
, is_long
);
3747 /* XXX: make it portable */
3751 char_size
= sizeof(nwchar_t
);
3752 if (tokcstr
.size
<= char_size
)
3753 error("empty character constant");
3754 if (tokcstr
.size
> 2 * char_size
)
3755 warning("multi-character character constant");
3757 tokc
.i
= *(int8_t *)tokcstr
.data
;
3760 tokc
.i
= *(nwchar_t
*)tokcstr
.data
;
3764 tokc
.cstr
= &tokcstr
;
3778 } else if (c
== '<') {
3796 } else if (c
== '>') {
3814 } else if (c
== '=') {
3827 } else if (c
== '=') {
3840 } else if (c
== '=') {
3853 } else if (c
== '=') {
3856 } else if (c
== '>') {
3864 PARSE2('!', '!', '=', TOK_NE
)
3865 PARSE2('=', '=', '=', TOK_EQ
)
3866 PARSE2('*', '*', '=', TOK_A_MUL
)
3867 PARSE2('%', '%', '=', TOK_A_MOD
)
3868 PARSE2('^', '^', '=', TOK_A_XOR
)
3870 /* comments or operator */
3874 p
= parse_comment(p
);
3876 } else if (c
== '/') {
3877 p
= parse_line_comment(p
);
3879 } else if (c
== '=') {
3899 case '$': /* only used in assembler */
3900 case '@': /* dito */
3905 error("unrecognized character \\x%02x", c
);
3910 #if defined(PARSE_DEBUG)
3911 printf("token = %s\n", get_tok_str(tok
, &tokc
));
3915 /* return next token without macro substitution. Can read input from
3917 static void next_nomacro(void)
3923 TOK_GET(tok
, macro_ptr
, tokc
);
3924 if (tok
== TOK_LINENUM
) {
3925 file
->line_num
= tokc
.i
;
3934 /* substitute args in macro_str and return allocated string */
3935 static int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
3937 int *st
, last_tok
, t
, notfirst
;
3946 TOK_GET(t
, macro_str
, cval
);
3951 TOK_GET(t
, macro_str
, cval
);
3954 s
= sym_find2(args
, t
);
3961 cstr_ccat(&cstr
, ' ');
3962 TOK_GET(t
, st
, cval
);
3963 cstr_cat(&cstr
, get_tok_str(t
, &cval
));
3966 cstr_ccat(&cstr
, '\0');
3968 printf("stringize: %s\n", (char *)cstr
.data
);
3972 tok_str_add2(&str
, TOK_STR
, &cval
);
3975 tok_str_add2(&str
, t
, &cval
);
3977 } else if (t
>= TOK_IDENT
) {
3978 s
= sym_find2(args
, t
);
3981 /* if '##' is present before or after, no arg substitution */
3982 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
3983 /* special case for var arg macros : ## eats the
3984 ',' if empty VA_ARGS variable. */
3985 /* XXX: test of the ',' is not 100%
3986 reliable. should fix it to avoid security
3988 if (gnu_ext
&& s
->type
.t
&&
3989 last_tok
== TOK_TWOSHARPS
&&
3990 str
.len
>= 2 && str
.str
[str
.len
- 2] == ',') {
3992 /* suppress ',' '##' */
3995 /* suppress '##' and add variable */
4003 TOK_GET(t1
, st
, cval
);
4006 tok_str_add2(&str
, t1
, &cval
);
4010 /* NOTE: the stream cannot be read when macro
4011 substituing an argument */
4012 macro_subst(&str
, nested_list
, st
, NULL
);
4015 tok_str_add(&str
, t
);
4018 tok_str_add2(&str
, t
, &cval
);
4022 tok_str_add(&str
, 0);
4026 static char const ab_month_name
[12][4] =
4028 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4029 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4032 /* do macro substitution of current token with macro 's' and add
4033 result to (tok_str,tok_len). 'nested_list' is the list of all
4034 macros we got inside to avoid recursing. Return non zero if no
4035 substitution needs to be done */
4036 static int macro_subst_tok(TokenString
*tok_str
,
4037 Sym
**nested_list
, Sym
*s
, struct macro_level
**can_read_stream
)
4039 Sym
*args
, *sa
, *sa1
;
4040 int mstr_allocated
, parlevel
, *mstr
, t
, t1
;
4047 /* if symbol is a macro, prepare substitution */
4048 /* special macros */
4049 if (tok
== TOK___LINE__
) {
4050 snprintf(buf
, sizeof(buf
), "%d", file
->line_num
);
4054 } else if (tok
== TOK___FILE__
) {
4055 cstrval
= file
->filename
;
4057 } else if (tok
== TOK___DATE__
|| tok
== TOK___TIME__
) {
4062 tm
= localtime(&ti
);
4063 if (tok
== TOK___DATE__
) {
4064 snprintf(buf
, sizeof(buf
), "%s %2d %d",
4065 ab_month_name
[tm
->tm_mon
], tm
->tm_mday
, tm
->tm_year
+ 1900);
4067 snprintf(buf
, sizeof(buf
), "%02d:%02d:%02d",
4068 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
);
4075 cstr_cat(&cstr
, cstrval
);
4076 cstr_ccat(&cstr
, '\0');
4078 tok_str_add2(tok_str
, t1
, &cval
);
4083 if (s
->type
.t
== MACRO_FUNC
) {
4084 /* NOTE: we do not use next_nomacro to avoid eating the
4085 next token. XXX: find better solution */
4089 if (t
== 0 && can_read_stream
) {
4090 /* end of macro stream: we must look at the token
4091 after in the file */
4092 struct macro_level
*ml
= *can_read_stream
;
4098 *can_read_stream
= ml
-> prev
;
4103 /* XXX: incorrect with comments */
4104 ch
= file
->buf_ptr
[0];
4105 while (is_space(ch
) || ch
== '\n')
4109 if (t
!= '(') /* no macro subst */
4112 /* argument macro */
4117 /* NOTE: empty args are allowed, except if no args */
4119 /* handle '()' case */
4120 if (!args
&& !sa
&& tok
== ')')
4123 error("macro '%s' used with too many args",
4124 get_tok_str(s
->v
, 0));
4127 /* NOTE: non zero sa->t indicates VA_ARGS */
4128 while ((parlevel
> 0 ||
4130 (tok
!= ',' || sa
->type
.t
))) &&
4134 else if (tok
== ')')
4136 tok_str_add2(&str
, tok
, &tokc
);
4139 tok_str_add(&str
, 0);
4140 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, sa
->type
.t
, (int)str
.str
);
4143 /* special case for gcc var args: add an empty
4144 var arg argument if it is omitted */
4145 if (sa
&& sa
->type
.t
&& gnu_ext
)
4155 error("macro '%s' used with too few args",
4156 get_tok_str(s
->v
, 0));
4159 /* now subst each arg */
4160 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
4165 tok_str_free((int *)sa
->c
);
4171 sym_push2(nested_list
, s
->v
, 0, 0);
4172 macro_subst(tok_str
, nested_list
, mstr
, can_read_stream
);
4173 /* pop nested defined symbol */
4175 *nested_list
= sa1
->prev
;
4183 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4184 return the resulting string (which must be freed). */
4185 static inline int *macro_twosharps(const int *macro_str
)
4188 const int *macro_ptr1
, *start_macro_ptr
, *ptr
, *saved_macro_ptr
;
4190 const char *p1
, *p2
;
4192 TokenString macro_str1
;
4195 start_macro_ptr
= macro_str
;
4196 /* we search the first '##' */
4198 macro_ptr1
= macro_str
;
4199 TOK_GET(t
, macro_str
, cval
);
4200 /* nothing more to do if end of string */
4203 if (*macro_str
== TOK_TWOSHARPS
)
4207 /* we saw '##', so we need more processing to handle it */
4209 tok_str_new(¯o_str1
);
4213 /* add all tokens seen so far */
4214 for(ptr
= start_macro_ptr
; ptr
< macro_ptr1
;) {
4215 TOK_GET(t
, ptr
, cval
);
4216 tok_str_add2(¯o_str1
, t
, &cval
);
4218 saved_macro_ptr
= macro_ptr
;
4219 /* XXX: get rid of the use of macro_ptr here */
4220 macro_ptr
= (int *)macro_str
;
4222 while (*macro_ptr
== TOK_TWOSHARPS
) {
4224 macro_ptr1
= macro_ptr
;
4227 TOK_GET(t
, macro_ptr
, cval
);
4228 /* We concatenate the two tokens if we have an
4229 identifier or a preprocessing number */
4231 p1
= get_tok_str(tok
, &tokc
);
4232 cstr_cat(&cstr
, p1
);
4233 p2
= get_tok_str(t
, &cval
);
4234 cstr_cat(&cstr
, p2
);
4235 cstr_ccat(&cstr
, '\0');
4237 if ((tok
>= TOK_IDENT
|| tok
== TOK_PPNUM
) &&
4238 (t
>= TOK_IDENT
|| t
== TOK_PPNUM
)) {
4239 if (tok
== TOK_PPNUM
) {
4240 /* if number, then create a number token */
4241 /* NOTE: no need to allocate because
4242 tok_str_add2() does it */
4243 cstr_reset(&tokcstr
);
4246 tokc
.cstr
= &tokcstr
;
4248 /* if identifier, we must do a test to
4249 validate we have a correct identifier */
4250 if (t
== TOK_PPNUM
) {
4260 if (!isnum(c
) && !isid(c
))
4264 ts
= tok_alloc(cstr
.data
, strlen(cstr
.data
));
4265 tok
= ts
->tok
; /* modify current token */
4268 const char *str
= cstr
.data
;
4269 const unsigned char *q
;
4271 /* we look for a valid token */
4272 /* XXX: do more extensive checks */
4273 if (!strcmp(str
, ">>=")) {
4275 } else if (!strcmp(str
, "<<=")) {
4277 } else if (strlen(str
) == 2) {
4278 /* search in two bytes table */
4283 if (q
[0] == str
[0] && q
[1] == str
[1])
4290 /* NOTE: because get_tok_str use a static buffer,
4293 p1
= get_tok_str(tok
, &tokc
);
4294 cstr_cat(&cstr
, p1
);
4295 cstr_ccat(&cstr
, '\0');
4296 p2
= get_tok_str(t
, &cval
);
4297 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr
.data
, p2
);
4298 /* cannot merge tokens: just add them separately */
4299 tok_str_add2(¯o_str1
, tok
, &tokc
);
4300 /* XXX: free associated memory ? */
4307 tok_str_add2(¯o_str1
, tok
, &tokc
);
4312 macro_ptr
= (int *)saved_macro_ptr
;
4314 tok_str_add(¯o_str1
, 0);
4315 return macro_str1
.str
;
4319 /* do macro substitution of macro_str and add result to
4320 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4321 inside to avoid recursing. */
4322 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
4323 const int *macro_str
, struct macro_level
** can_read_stream
)
4330 struct macro_level ml
;
4332 /* first scan for '##' operator handling */
4334 macro_str1
= macro_twosharps(ptr
);
4338 /* NOTE: ptr == NULL can only happen if tokens are read from
4339 file stream due to a macro function call */
4342 TOK_GET(t
, ptr
, cval
);
4347 /* if nested substitution, do nothing */
4348 if (sym_find2(*nested_list
, t
))
4351 if (can_read_stream
)
4352 ml
.prev
= *can_read_stream
, *can_read_stream
= &ml
;
4353 macro_ptr
= (int *)ptr
;
4355 ret
= macro_subst_tok(tok_str
, nested_list
, s
, can_read_stream
);
4356 ptr
= (int *)macro_ptr
;
4358 if (can_read_stream
&& *can_read_stream
== &ml
)
4359 *can_read_stream
= ml
.prev
;
4364 tok_str_add2(tok_str
, t
, &cval
);
4368 tok_str_free(macro_str1
);
4371 /* return next token with macro substitution */
4372 static void next(void)
4374 Sym
*nested_list
, *s
;
4376 struct macro_level
*ml
;
4381 /* if not reading from macro substituted string, then try
4382 to substitute macros */
4383 if (tok
>= TOK_IDENT
&&
4384 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
4385 s
= define_find(tok
);
4387 /* we have a macro: we try to substitute */
4391 if (macro_subst_tok(&str
, &nested_list
, s
, &ml
) == 0) {
4392 /* substitution done, NOTE: maybe empty */
4393 tok_str_add(&str
, 0);
4394 macro_ptr
= str
.str
;
4395 macro_ptr_allocated
= str
.str
;
4402 /* end of macro or end of unget buffer */
4403 if (unget_buffer_enabled
) {
4404 macro_ptr
= unget_saved_macro_ptr
;
4405 unget_buffer_enabled
= 0;
4407 /* end of macro string: free it */
4408 tok_str_free(macro_ptr_allocated
);
4415 /* convert preprocessor tokens into C tokens */
4416 if (tok
== TOK_PPNUM
&&
4417 (parse_flags
& PARSE_FLAG_TOK_NUM
)) {
4418 parse_number((char *)tokc
.cstr
->data
);
4422 /* push back current token and set current token to 'last_tok'. Only
4423 identifier case handled for labels. */
4424 static inline void unget_tok(int last_tok
)
4428 unget_saved_macro_ptr
= macro_ptr
;
4429 unget_buffer_enabled
= 1;
4430 q
= unget_saved_buffer
;
4433 n
= tok_ext_size(tok
) - 1;
4436 *q
= 0; /* end of token string */
4441 void swap(int *p
, int *q
)
4449 void vsetc(CType
*type
, int r
, CValue
*vc
)
4453 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4454 error("memory full");
4455 /* cannot let cpu flags if other instruction are generated. Also
4456 avoid leaving VT_JMP anywhere except on the top of the stack
4457 because it would complicate the code generator. */
4458 if (vtop
>= vstack
) {
4459 v
= vtop
->r
& VT_VALMASK
;
4460 if (v
== VT_CMP
|| (v
& ~1) == VT_JMP
)
4466 vtop
->r2
= VT_CONST
;
4470 /* push integer constant */
4475 vsetc(&int_type
, VT_CONST
, &cval
);
4478 /* Return a static symbol pointing to a section */
4479 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
4480 unsigned long offset
, unsigned long size
)
4486 sym
= global_identifier_push(v
, type
->t
| VT_STATIC
, 0);
4487 sym
->type
.ref
= type
->ref
;
4488 sym
->r
= VT_CONST
| VT_SYM
;
4489 put_extern_sym(sym
, sec
, offset
, size
);
4493 /* push a reference to a section offset by adding a dummy symbol */
4494 static void vpush_ref(CType
*type
, Section
*sec
, unsigned long offset
, unsigned long size
)
4499 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4500 vtop
->sym
= get_sym_ref(type
, sec
, offset
, size
);
4503 /* define a new external reference to a symbol 'v' of type 'u' */
4504 static Sym
*external_global_sym(int v
, CType
*type
, int r
)
4510 /* push forward reference */
4511 s
= global_identifier_push(v
, type
->t
| VT_EXTERN
, 0);
4512 s
->type
.ref
= type
->ref
;
4513 s
->r
= r
| VT_CONST
| VT_SYM
;
4518 /* define a new external reference to a symbol 'v' of type 'u' */
4519 static Sym
*external_sym(int v
, CType
*type
, int r
)
4525 /* push forward reference */
4526 s
= sym_push(v
, type
, r
| VT_CONST
| VT_SYM
, 0);
4527 s
->type
.t
|= VT_EXTERN
;
4529 if (!is_compatible_types(&s
->type
, type
))
4530 error("incompatible types for redefinition of '%s'",
4531 get_tok_str(v
, NULL
));
4536 /* push a reference to global symbol v */
4537 static void vpush_global_sym(CType
*type
, int v
)
4542 sym
= external_global_sym(v
, type
, 0);
4544 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4548 void vset(CType
*type
, int r
, int v
)
4553 vsetc(type
, r
, &cval
);
4556 void vseti(int r
, int v
)
4572 void vpushv(SValue
*v
)
4574 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4575 error("memory full");
4585 /* save r to the memory stack, and mark it as being free */
4586 void save_reg(int r
)
4588 int l
, saved
, size
, align
;
4592 /* modify all stack values */
4595 for(p
=vstack
;p
<=vtop
;p
++) {
4596 if ((p
->r
& VT_VALMASK
) == r
||
4597 (p
->r2
& VT_VALMASK
) == r
) {
4598 /* must save value on stack if not already done */
4600 /* NOTE: must reload 'r' because r might be equal to r2 */
4601 r
= p
->r
& VT_VALMASK
;
4602 /* store register in the stack */
4604 if ((p
->r
& VT_LVAL
) ||
4605 (!is_float(type
->t
) && (type
->t
& VT_BTYPE
) != VT_LLONG
))
4607 size
= type_size(type
, &align
);
4608 loc
= (loc
- size
) & -align
;
4609 sv
.type
.t
= type
->t
;
4610 sv
.r
= VT_LOCAL
| VT_LVAL
;
4613 #ifdef TCC_TARGET_I386
4614 /* x86 specific: need to pop fp register ST0 if saved */
4615 if (r
== TREG_ST0
) {
4616 o(0xd9dd); /* fstp %st(1) */
4619 /* special long long case */
4620 if ((type
->t
& VT_BTYPE
) == VT_LLONG
) {
4627 /* mark that stack entry as being saved on the stack */
4628 if (p
->r
& VT_LVAL
) {
4629 /* also clear the bounded flag because the
4630 relocation address of the function was stored in
4632 p
->r
= (p
->r
& ~(VT_VALMASK
| VT_BOUNDED
)) | VT_LLOCAL
;
4634 p
->r
= lvalue_type(p
->type
.t
) | VT_LOCAL
;
4642 /* find a register of class 'rc2' with at most one reference on stack.
4643 * If none, call get_reg(rc) */
4644 int get_reg_ex(int rc
, int rc2
)
4649 for(r
=0;r
<NB_REGS
;r
++) {
4650 if (reg_classes
[r
] & rc2
) {
4653 for(p
= vstack
; p
<= vtop
; p
++) {
4654 if ((p
->r
& VT_VALMASK
) == r
||
4655 (p
->r2
& VT_VALMASK
) == r
)
4665 /* find a free register of class 'rc'. If none, save one register */
4671 /* find a free register */
4672 for(r
=0;r
<NB_REGS
;r
++) {
4673 if (reg_classes
[r
] & rc
) {
4674 for(p
=vstack
;p
<=vtop
;p
++) {
4675 if ((p
->r
& VT_VALMASK
) == r
||
4676 (p
->r2
& VT_VALMASK
) == r
)
4684 /* no register left : free the first one on the stack (VERY
4685 IMPORTANT to start from the bottom to ensure that we don't
4686 spill registers used in gen_opi()) */
4687 for(p
=vstack
;p
<=vtop
;p
++) {
4688 r
= p
->r
& VT_VALMASK
;
4689 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
))
4691 /* also look at second register (if long long) */
4692 r
= p
->r2
& VT_VALMASK
;
4693 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
4699 /* Should never comes here */
4703 /* save registers up to (vtop - n) stack entry */
4704 void save_regs(int n
)
4709 for(p
= vstack
;p
<= p1
; p
++) {
4710 r
= p
->r
& VT_VALMASK
;
4717 /* move register 's' to 'r', and flush previous value of r to memory
4719 void move_reg(int r
, int s
)
4732 /* get address of vtop (vtop MUST BE an lvalue) */
4735 vtop
->r
&= ~VT_LVAL
;
4736 /* tricky: if saved lvalue, then we can go back to lvalue */
4737 if ((vtop
->r
& VT_VALMASK
) == VT_LLOCAL
)
4738 vtop
->r
= (vtop
->r
& ~(VT_VALMASK
| VT_LVAL_TYPE
)) | VT_LOCAL
| VT_LVAL
;
4741 #ifdef CONFIG_TCC_BCHECK
4742 /* generate lvalue bound code */
4748 vtop
->r
&= ~VT_MUSTBOUND
;
4749 /* if lvalue, then use checking code before dereferencing */
4750 if (vtop
->r
& VT_LVAL
) {
4751 /* if not VT_BOUNDED value, then make one */
4752 if (!(vtop
->r
& VT_BOUNDED
)) {
4753 lval_type
= vtop
->r
& (VT_LVAL_TYPE
| VT_LVAL
);
4754 /* must save type because we must set it to int to get pointer */
4756 vtop
->type
.t
= VT_INT
;
4759 gen_bounded_ptr_add();
4760 vtop
->r
|= lval_type
;
4763 /* then check for dereferencing */
4764 gen_bounded_ptr_deref();
4769 /* store vtop a register belonging to class 'rc'. lvalues are
4770 converted to values. Cannot be used if cannot be converted to
4771 register value (such as structures). */
4774 int r
, r2
, rc2
, bit_pos
, bit_size
, size
, align
, i
;
4775 unsigned long long ll
;
4777 /* NOTE: get_reg can modify vstack[] */
4778 if (vtop
->type
.t
& VT_BITFIELD
) {
4779 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
4780 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
4781 /* remove bit field info to avoid loops */
4782 vtop
->type
.t
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
4783 /* generate shifts */
4784 vpushi(32 - (bit_pos
+ bit_size
));
4786 vpushi(32 - bit_size
);
4787 /* NOTE: transformed to SHR if unsigned */
4791 if (is_float(vtop
->type
.t
) &&
4792 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4795 unsigned long offset
;
4797 /* XXX: unify with initializers handling ? */
4798 /* CPUs usually cannot use float constants, so we store them
4799 generically in data segment */
4800 size
= type_size(&vtop
->type
, &align
);
4801 offset
= (data_section
->data_offset
+ align
- 1) & -align
;
4802 data_section
->data_offset
= offset
;
4803 /* XXX: not portable yet */
4804 ptr
= section_ptr_add(data_section
, size
);
4807 ptr
[i
] = vtop
->c
.tab
[i
];
4808 sym
= get_sym_ref(&vtop
->type
, data_section
, offset
, size
<< 2);
4809 vtop
->r
|= VT_LVAL
| VT_SYM
;
4813 #ifdef CONFIG_TCC_BCHECK
4814 if (vtop
->r
& VT_MUSTBOUND
)
4818 r
= vtop
->r
& VT_VALMASK
;
4819 /* need to reload if:
4821 - lvalue (need to dereference pointer)
4822 - already a register, but not in the right class */
4823 if (r
>= VT_CONST
||
4824 (vtop
->r
& VT_LVAL
) ||
4825 !(reg_classes
[r
] & rc
) ||
4826 ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
&&
4827 !(reg_classes
[vtop
->r2
] & rc
))) {
4829 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
4830 /* two register type load : expand to two words
4832 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4835 vtop
->c
.ui
= ll
; /* first word */
4837 vtop
->r
= r
; /* save register value */
4838 vpushi(ll
>> 32); /* second word */
4839 } else if (r
>= VT_CONST
|| /* XXX: test to VT_CONST incorrect ? */
4840 (vtop
->r
& VT_LVAL
)) {
4841 /* We do not want to modifier the long long
4842 pointer here, so the safest (and less
4843 efficient) is to save all the other registers
4844 in the stack. XXX: totally inefficient. */
4846 /* load from memory */
4849 vtop
[-1].r
= r
; /* save register value */
4850 /* increment pointer to get second word */
4851 vtop
->type
.t
= VT_INT
;
4857 /* move registers */
4860 vtop
[-1].r
= r
; /* save register value */
4861 vtop
->r
= vtop
[-1].r2
;
4863 /* allocate second register */
4870 /* write second register */
4872 } else if ((vtop
->r
& VT_LVAL
) && !is_float(vtop
->type
.t
)) {
4874 /* lvalue of scalar type : need to use lvalue type
4875 because of possible cast */
4878 /* compute memory access type */
4879 if (vtop
->r
& VT_LVAL_BYTE
)
4881 else if (vtop
->r
& VT_LVAL_SHORT
)
4883 if (vtop
->r
& VT_LVAL_UNSIGNED
)
4887 /* restore wanted type */
4890 /* one register type load */
4895 #ifdef TCC_TARGET_C67
4896 /* uses register pairs for doubles */
4897 if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
)
4904 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4905 void gv2(int rc1
, int rc2
)
4909 /* generate more generic register first. But VT_JMP or VT_CMP
4910 values must be generated first in all cases to avoid possible
4912 v
= vtop
[0].r
& VT_VALMASK
;
4913 if (v
!= VT_CMP
&& (v
& ~1) != VT_JMP
&& rc1
<= rc2
) {
4918 /* test if reload is needed for first register */
4919 if ((vtop
[-1].r
& VT_VALMASK
) >= VT_CONST
) {
4929 /* test if reload is needed for first register */
4930 if ((vtop
[0].r
& VT_VALMASK
) >= VT_CONST
) {
4936 /* expand long long on stack in two int registers */
4941 u
= vtop
->type
.t
& VT_UNSIGNED
;
4944 vtop
[0].r
= vtop
[-1].r2
;
4945 vtop
[0].r2
= VT_CONST
;
4946 vtop
[-1].r2
= VT_CONST
;
4947 vtop
[0].type
.t
= VT_INT
| u
;
4948 vtop
[-1].type
.t
= VT_INT
| u
;
4951 #ifdef TCC_TARGET_ARM
4952 /* expand long long on stack */
4953 void lexpand_nr(void)
4957 u
= vtop
->type
.t
& VT_UNSIGNED
;
4959 vtop
->r2
= VT_CONST
;
4960 vtop
->type
.t
= VT_INT
| u
;
4961 v
=vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
);
4962 if (v
== VT_CONST
) {
4963 vtop
[-1].c
.ui
= vtop
->c
.ull
;
4964 vtop
->c
.ui
= vtop
->c
.ull
>> 32;
4966 } else if (v
== (VT_LVAL
|VT_CONST
) || v
== (VT_LVAL
|VT_LOCAL
)) {
4968 vtop
->r
= vtop
[-1].r
;
4969 } else if (v
> VT_CONST
) {
4973 vtop
->r
= vtop
[-1].r2
;
4974 vtop
[-1].r2
= VT_CONST
;
4975 vtop
[-1].type
.t
= VT_INT
| u
;
4979 /* build a long long from two ints */
4982 gv2(RC_INT
, RC_INT
);
4983 vtop
[-1].r2
= vtop
[0].r
;
4984 vtop
[-1].type
.t
= t
;
4988 /* rotate n first stack elements to the bottom
4989 I1 ... In -> I2 ... In I1 [top is right]
4997 for(i
=-n
+1;i
!=0;i
++)
4998 vtop
[i
] = vtop
[i
+1];
5002 /* rotate n first stack elements to the top
5003 I1 ... In -> In I1 ... I(n-1) [top is right]
5011 for(i
= 0;i
< n
- 1; i
++)
5012 vtop
[-i
] = vtop
[-i
- 1];
5016 #ifdef TCC_TARGET_ARM
5017 /* like vrott but in other direction
5018 In ... I1 -> I(n-1) ... I1 In [top is right]
5026 for(i
= n
- 1; i
> 0; i
--)
5027 vtop
[-i
] = vtop
[-i
+ 1];
5032 /* pop stack value */
5036 v
= vtop
->r
& VT_VALMASK
;
5037 #ifdef TCC_TARGET_I386
5038 /* for x86, we need to pop the FP stack */
5039 if (v
== TREG_ST0
&& !nocode_wanted
) {
5040 o(0xd9dd); /* fstp %st(1) */
5043 if (v
== VT_JMP
|| v
== VT_JMPI
) {
5044 /* need to put correct jump if && or || without test */
5050 /* convert stack entry to register and duplicate its value in another
5058 if ((t
& VT_BTYPE
) == VT_LLONG
) {
5065 /* stack: H L L1 H1 */
5073 /* duplicate value */
5084 load(r1
, &sv
); /* move r to r1 */
5086 /* duplicates value */
5091 /* generate CPU independent (unsigned) long long operations */
5092 void gen_opl(int op
)
5094 int t
, a
, b
, op1
, c
, i
;
5101 func
= TOK___divdi3
;
5104 func
= TOK___udivdi3
;
5107 func
= TOK___moddi3
;
5110 func
= TOK___umoddi3
;
5112 /* call generic long long function */
5113 vpush_global_sym(&func_old_type
, func
);
5118 vtop
->r2
= REG_LRET
;
5131 /* stack: L1 H1 L2 H2 */
5136 vtop
[-2] = vtop
[-3];
5139 /* stack: H1 H2 L1 L2 */
5145 /* stack: H1 H2 L1 L2 ML MH */
5148 /* stack: ML MH H1 H2 L1 L2 */
5152 /* stack: ML MH H1 L2 H2 L1 */
5157 /* stack: ML MH M1 M2 */
5160 } else if (op
== '+' || op
== '-') {
5161 /* XXX: add non carry method too (for MIPS or alpha) */
5167 /* stack: H1 H2 (L1 op L2) */
5170 gen_op(op1
+ 1); /* TOK_xxxC2 */
5173 /* stack: H1 H2 (L1 op L2) */
5176 /* stack: (L1 op L2) H1 H2 */
5178 /* stack: (L1 op L2) (H1 op H2) */
5186 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
5187 t
= vtop
[-1].type
.t
;
5191 /* stack: L H shift */
5193 /* constant: simpler */
5194 /* NOTE: all comments are for SHL. the other cases are
5195 done by swaping words */
5206 if (op
!= TOK_SAR
) {
5239 /* XXX: should provide a faster fallback on x86 ? */
5242 func
= TOK___sardi3
;
5245 func
= TOK___shrdi3
;
5248 func
= TOK___shldi3
;
5254 /* compare operations */
5260 /* stack: L1 H1 L2 H2 */
5262 vtop
[-1] = vtop
[-2];
5264 /* stack: L1 L2 H1 H2 */
5267 /* when values are equal, we need to compare low words. since
5268 the jump is inverted, we invert the test too. */
5271 else if (op1
== TOK_GT
)
5273 else if (op1
== TOK_ULT
)
5275 else if (op1
== TOK_UGT
)
5280 if (op1
!= TOK_NE
) {
5284 /* generate non equal test */
5285 /* XXX: NOT PORTABLE yet */
5289 #if defined(TCC_TARGET_I386)
5290 b
= psym(0x850f, 0);
5291 #elif defined(TCC_TARGET_ARM)
5293 o(0x1A000000 | encbranch(ind
, 0, 1));
5294 #elif defined(TCC_TARGET_C67)
5295 error("not implemented");
5297 #error not supported
5301 /* compare low. Always unsigned */
5305 else if (op1
== TOK_LE
)
5307 else if (op1
== TOK_GT
)
5309 else if (op1
== TOK_GE
)
5319 /* handle integer constant optimizations and various machine
5321 void gen_opic(int op
)
5328 /* currently, we cannot do computations with forward symbols */
5329 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5330 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5334 case '+': v1
->c
.i
+= fc
; break;
5335 case '-': v1
->c
.i
-= fc
; break;
5336 case '&': v1
->c
.i
&= fc
; break;
5337 case '^': v1
->c
.i
^= fc
; break;
5338 case '|': v1
->c
.i
|= fc
; break;
5339 case '*': v1
->c
.i
*= fc
; break;
5346 /* if division by zero, generate explicit division */
5349 error("division by zero in constant");
5353 default: v1
->c
.i
/= fc
; break;
5354 case '%': v1
->c
.i
%= fc
; break;
5355 case TOK_UDIV
: v1
->c
.i
= (unsigned)v1
->c
.i
/ fc
; break;
5356 case TOK_UMOD
: v1
->c
.i
= (unsigned)v1
->c
.i
% fc
; break;
5359 case TOK_SHL
: v1
->c
.i
<<= fc
; break;
5360 case TOK_SHR
: v1
->c
.i
= (unsigned)v1
->c
.i
>> fc
; break;
5361 case TOK_SAR
: v1
->c
.i
>>= fc
; break;
5363 case TOK_ULT
: v1
->c
.i
= (unsigned)v1
->c
.i
< (unsigned)fc
; break;
5364 case TOK_UGE
: v1
->c
.i
= (unsigned)v1
->c
.i
>= (unsigned)fc
; break;
5365 case TOK_EQ
: v1
->c
.i
= v1
->c
.i
== fc
; break;
5366 case TOK_NE
: v1
->c
.i
= v1
->c
.i
!= fc
; break;
5367 case TOK_ULE
: v1
->c
.i
= (unsigned)v1
->c
.i
<= (unsigned)fc
; break;
5368 case TOK_UGT
: v1
->c
.i
= (unsigned)v1
->c
.i
> (unsigned)fc
; break;
5369 case TOK_LT
: v1
->c
.i
= v1
->c
.i
< fc
; break;
5370 case TOK_GE
: v1
->c
.i
= v1
->c
.i
>= fc
; break;
5371 case TOK_LE
: v1
->c
.i
= v1
->c
.i
<= fc
; break;
5372 case TOK_GT
: v1
->c
.i
= v1
->c
.i
> fc
; break;
5374 case TOK_LAND
: v1
->c
.i
= v1
->c
.i
&& fc
; break;
5375 case TOK_LOR
: v1
->c
.i
= v1
->c
.i
|| fc
; break;
5381 /* if commutative ops, put c2 as constant */
5382 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
5383 op
== '|' || op
== '*')) {
5388 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
5391 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
5392 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
5398 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
5399 /* try to use shifts instead of muls or divs */
5400 if (fc
> 0 && (fc
& (fc
- 1)) == 0) {
5409 else if (op
== TOK_PDIV
)
5415 } else if (c2
&& (op
== '+' || op
== '-') &&
5416 (vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) ==
5417 (VT_CONST
| VT_SYM
)) {
5418 /* symbol + constant case */
5425 if (!nocode_wanted
) {
5426 /* call low level op generator */
5435 /* generate a floating point operation with constant propagation */
5436 void gen_opif(int op
)
5444 /* currently, we cannot do computations with forward symbols */
5445 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5446 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5448 if (v1
->type
.t
== VT_FLOAT
) {
5451 } else if (v1
->type
.t
== VT_DOUBLE
) {
5459 /* NOTE: we only do constant propagation if finite number (not
5460 NaN or infinity) (ANSI spec) */
5461 if (!ieee_finite(f1
) || !ieee_finite(f2
))
5465 case '+': f1
+= f2
; break;
5466 case '-': f1
-= f2
; break;
5467 case '*': f1
*= f2
; break;
5471 error("division by zero in constant");
5476 /* XXX: also handles tests ? */
5480 /* XXX: overflow test ? */
5481 if (v1
->type
.t
== VT_FLOAT
) {
5483 } else if (v1
->type
.t
== VT_DOUBLE
) {
5491 if (!nocode_wanted
) {
5499 static int pointed_size(CType
*type
)
5502 return type_size(pointed_type(type
), &align
);
5505 static inline int is_null_pointer(SValue
*p
)
5507 if ((p
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
5509 return ((p
->type
.t
& VT_BTYPE
) == VT_INT
&& p
->c
.i
== 0) ||
5510 ((p
->type
.t
& VT_BTYPE
) == VT_LLONG
&& p
->c
.ll
== 0);
5513 static inline int is_integer_btype(int bt
)
5515 return (bt
== VT_BYTE
|| bt
== VT_SHORT
||
5516 bt
== VT_INT
|| bt
== VT_LLONG
);
5519 /* check types for comparison or substraction of pointers */
5520 static void check_comparison_pointer_types(SValue
*p1
, SValue
*p2
, int op
)
5522 CType
*type1
, *type2
, tmp_type1
, tmp_type2
;
5525 /* null pointers are accepted for all comparisons as gcc */
5526 if (is_null_pointer(p1
) || is_null_pointer(p2
))
5530 bt1
= type1
->t
& VT_BTYPE
;
5531 bt2
= type2
->t
& VT_BTYPE
;
5532 /* accept comparison between pointer and integer with a warning */
5533 if ((is_integer_btype(bt1
) || is_integer_btype(bt2
)) && op
!= '-') {
5534 warning("comparison between pointer and integer");
5538 /* both must be pointers or implicit function pointers */
5539 if (bt1
== VT_PTR
) {
5540 type1
= pointed_type(type1
);
5541 } else if (bt1
!= VT_FUNC
)
5542 goto invalid_operands
;
5544 if (bt2
== VT_PTR
) {
5545 type2
= pointed_type(type2
);
5546 } else if (bt2
!= VT_FUNC
) {
5548 error("invalid operands to binary %s", get_tok_str(op
, NULL
));
5550 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
5551 (type2
->t
& VT_BTYPE
) == VT_VOID
)
5555 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5556 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5557 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
5558 /* gcc-like error if '-' is used */
5560 goto invalid_operands
;
5562 warning("comparison of distinct pointer types lacks a cast");
5566 /* generic gen_op: handles types problems */
5569 int u
, t1
, t2
, bt1
, bt2
, t
;
5572 t1
= vtop
[-1].type
.t
;
5573 t2
= vtop
[0].type
.t
;
5574 bt1
= t1
& VT_BTYPE
;
5575 bt2
= t2
& VT_BTYPE
;
5577 if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
5578 /* at least one operand is a pointer */
5579 /* relationnal op: must be both pointers */
5580 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
5581 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5582 /* pointers are handled are unsigned */
5583 t
= VT_INT
| VT_UNSIGNED
;
5586 /* if both pointers, then it must be the '-' op */
5587 if (bt1
== VT_PTR
&& bt2
== VT_PTR
) {
5589 error("cannot use pointers here");
5590 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5591 /* XXX: check that types are compatible */
5592 u
= pointed_size(&vtop
[-1].type
);
5594 /* set to integer type */
5595 vtop
->type
.t
= VT_INT
;
5599 /* exactly one pointer : must be '+' or '-'. */
5600 if (op
!= '-' && op
!= '+')
5601 error("cannot use pointers here");
5602 /* Put pointer as first operand */
5603 if (bt2
== VT_PTR
) {
5607 type1
= vtop
[-1].type
;
5608 /* XXX: cast to int ? (long long case) */
5609 vpushi(pointed_size(&vtop
[-1].type
));
5611 #ifdef CONFIG_TCC_BCHECK
5612 /* if evaluating constant expression, no code should be
5613 generated, so no bound check */
5614 if (do_bounds_check
&& !const_wanted
) {
5615 /* if bounded pointers, we generate a special code to
5622 gen_bounded_ptr_add();
5628 /* put again type if gen_opic() swaped operands */
5631 } else if (is_float(bt1
) || is_float(bt2
)) {
5632 /* compute bigger type and do implicit casts */
5633 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
5635 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
5640 /* floats can only be used for a few operations */
5641 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
5642 (op
< TOK_ULT
|| op
> TOK_GT
))
5643 error("invalid operands for binary operation");
5645 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
5646 /* cast to biggest op */
5648 /* convert to unsigned if it does not fit in a long long */
5649 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
5650 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
5654 /* integer operations */
5656 /* convert to unsigned if it does not fit in an integer */
5657 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
5658 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
5661 /* XXX: currently, some unsigned operations are explicit, so
5662 we modify them here */
5663 if (t
& VT_UNSIGNED
) {
5670 else if (op
== TOK_LT
)
5672 else if (op
== TOK_GT
)
5674 else if (op
== TOK_LE
)
5676 else if (op
== TOK_GE
)
5683 /* special case for shifts and long long: we keep the shift as
5685 if (op
== TOK_SHR
|| op
== TOK_SAR
|| op
== TOK_SHL
)
5690 else if ((t
& VT_BTYPE
) == VT_LLONG
)
5694 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
5695 /* relationnal op: the result is an int */
5696 vtop
->type
.t
= VT_INT
;
5703 /* generic itof for unsigned long long case */
5704 void gen_cvt_itof1(int t
)
5706 if ((vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
)) ==
5707 (VT_LLONG
| VT_UNSIGNED
)) {
5710 vpush_global_sym(&func_old_type
, TOK___ulltof
);
5711 else if (t
== VT_DOUBLE
)
5712 vpush_global_sym(&func_old_type
, TOK___ulltod
);
5714 vpush_global_sym(&func_old_type
, TOK___ulltold
);
5724 /* generic ftoi for unsigned long long case */
5725 void gen_cvt_ftoi1(int t
)
5729 if (t
== (VT_LLONG
| VT_UNSIGNED
)) {
5730 /* not handled natively */
5731 st
= vtop
->type
.t
& VT_BTYPE
;
5733 vpush_global_sym(&func_old_type
, TOK___fixunssfdi
);
5734 else if (st
== VT_DOUBLE
)
5735 vpush_global_sym(&func_old_type
, TOK___fixunsdfdi
);
5737 vpush_global_sym(&func_old_type
, TOK___fixunsxfdi
);
5742 vtop
->r2
= REG_LRET
;
5748 /* force char or short cast */
5749 void force_charshort_cast(int t
)
5753 /* XXX: add optimization if lvalue : just change type and offset */
5758 if (t
& VT_UNSIGNED
) {
5759 vpushi((1 << bits
) - 1);
5770 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5771 static void gen_cast(CType
*type
)
5773 int sbt
, dbt
, sf
, df
, c
;
5775 /* special delayed cast for char/short */
5776 /* XXX: in some cases (multiple cascaded casts), it may still
5778 if (vtop
->r
& VT_MUSTCAST
) {
5779 vtop
->r
&= ~VT_MUSTCAST
;
5780 force_charshort_cast(vtop
->type
.t
);
5783 /* bitfields first get cast to ints */
5784 if (vtop
->type
.t
& VT_BITFIELD
) {
5788 dbt
= type
->t
& (VT_BTYPE
| VT_UNSIGNED
);
5789 sbt
= vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
);
5791 if (sbt
!= dbt
&& !nocode_wanted
) {
5794 c
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5796 /* convert from fp to fp */
5798 /* constant case: we can do it now */
5799 /* XXX: in ISOC, cannot do it if error in convert */
5800 if (dbt
== VT_FLOAT
&& sbt
== VT_DOUBLE
)
5801 vtop
->c
.f
= (float)vtop
->c
.d
;
5802 else if (dbt
== VT_FLOAT
&& sbt
== VT_LDOUBLE
)
5803 vtop
->c
.f
= (float)vtop
->c
.ld
;
5804 else if (dbt
== VT_DOUBLE
&& sbt
== VT_FLOAT
)
5805 vtop
->c
.d
= (double)vtop
->c
.f
;
5806 else if (dbt
== VT_DOUBLE
&& sbt
== VT_LDOUBLE
)
5807 vtop
->c
.d
= (double)vtop
->c
.ld
;
5808 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_FLOAT
)
5809 vtop
->c
.ld
= (long double)vtop
->c
.f
;
5810 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_DOUBLE
)
5811 vtop
->c
.ld
= (long double)vtop
->c
.d
;
5813 /* non constant case: generate code */
5817 /* convert int to fp */
5820 case VT_LLONG
| VT_UNSIGNED
:
5822 /* XXX: add const cases for long long */
5824 case VT_INT
| VT_UNSIGNED
:
5826 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.ui
; break;
5827 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.ui
; break;
5828 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.ui
; break;
5833 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.i
; break;
5834 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.i
; break;
5835 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.i
; break;
5841 #if !defined(TCC_TARGET_ARM)
5848 /* convert fp to int */
5849 /* we handle char/short/etc... with generic code */
5850 if (dbt
!= (VT_INT
| VT_UNSIGNED
) &&
5851 dbt
!= (VT_LLONG
| VT_UNSIGNED
) &&
5856 case VT_LLONG
| VT_UNSIGNED
:
5858 /* XXX: add const cases for long long */
5860 case VT_INT
| VT_UNSIGNED
:
5862 case VT_FLOAT
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5863 case VT_DOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5864 case VT_LDOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5870 case VT_FLOAT
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5871 case VT_DOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5872 case VT_LDOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5880 if (dbt
== VT_INT
&& (type
->t
& (VT_BTYPE
| VT_UNSIGNED
)) != dbt
) {
5881 /* additional cast for char/short/bool... */
5885 } else if ((dbt
& VT_BTYPE
) == VT_LLONG
) {
5886 if ((sbt
& VT_BTYPE
) != VT_LLONG
) {
5887 /* scalar to long long */
5889 if (sbt
== (VT_INT
| VT_UNSIGNED
))
5890 vtop
->c
.ll
= vtop
->c
.ui
;
5892 vtop
->c
.ll
= vtop
->c
.i
;
5894 /* machine independent conversion */
5896 /* generate high word */
5897 if (sbt
== (VT_INT
| VT_UNSIGNED
)) {
5905 /* patch second register */
5906 vtop
[-1].r2
= vtop
->r
;
5910 } else if (dbt
== VT_BOOL
) {
5911 /* scalar to bool */
5914 } else if ((dbt
& VT_BTYPE
) == VT_BYTE
||
5915 (dbt
& VT_BTYPE
) == VT_SHORT
) {
5916 force_charshort_cast(dbt
);
5917 } else if ((dbt
& VT_BTYPE
) == VT_INT
) {
5919 if (sbt
== VT_LLONG
) {
5920 /* from long long: just take low order word */
5924 /* if lvalue and single word type, nothing to do because
5925 the lvalue already contains the real type size (see
5926 VT_LVAL_xxx constants) */
5932 /* return type size. Put alignment at 'a' */
5933 static int type_size(CType
*type
, int *a
)
5938 bt
= type
->t
& VT_BTYPE
;
5939 if (bt
== VT_STRUCT
) {
5944 } else if (bt
== VT_PTR
) {
5945 if (type
->t
& VT_ARRAY
) {
5947 return type_size(&s
->type
, a
) * s
->c
;
5952 } else if (bt
== VT_LDOUBLE
) {
5954 return LDOUBLE_SIZE
;
5955 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
5956 #ifdef TCC_TARGET_I386
5962 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
5965 } else if (bt
== VT_SHORT
) {
5969 /* char, void, function, _Bool */
5975 /* return the pointed type of t */
5976 static inline CType
*pointed_type(CType
*type
)
5978 return &type
->ref
->type
;
5981 /* modify type so that its it is a pointer to type. */
5982 static void mk_pointer(CType
*type
)
5985 s
= sym_push(SYM_FIELD
, type
, 0, -1);
5986 type
->t
= VT_PTR
| (type
->t
& ~VT_TYPE
);
5990 /* compare function types. OLD functions match any new functions */
5991 static int is_compatible_func(CType
*type1
, CType
*type2
)
5997 if (!is_compatible_types(&s1
->type
, &s2
->type
))
5999 /* check func_call */
6002 /* XXX: not complete */
6003 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
6007 while (s1
!= NULL
) {
6010 if (!is_compatible_types(&s1
->type
, &s2
->type
))
6020 /* return true if type1 and type2 are exactly the same (including
6023 - enums are not checked as gcc __builtin_types_compatible_p ()
6025 static int is_compatible_types(CType
*type1
, CType
*type2
)
6029 t1
= type1
->t
& VT_TYPE
;
6030 t2
= type2
->t
& VT_TYPE
;
6031 /* XXX: bitfields ? */
6034 /* test more complicated cases */
6035 bt1
= t1
& VT_BTYPE
;
6036 if (bt1
== VT_PTR
) {
6037 type1
= pointed_type(type1
);
6038 type2
= pointed_type(type2
);
6039 return is_compatible_types(type1
, type2
);
6040 } else if (bt1
== VT_STRUCT
) {
6041 return (type1
->ref
== type2
->ref
);
6042 } else if (bt1
== VT_FUNC
) {
6043 return is_compatible_func(type1
, type2
);
6049 /* print a type. If 'varstr' is not NULL, then the variable is also
6050 printed in the type */
6052 /* XXX: add array and function pointers */
6053 void type_to_str(char *buf
, int buf_size
,
6054 CType
*type
, const char *varstr
)
6061 t
= type
->t
& VT_TYPE
;
6064 if (t
& VT_CONSTANT
)
6065 pstrcat(buf
, buf_size
, "const ");
6066 if (t
& VT_VOLATILE
)
6067 pstrcat(buf
, buf_size
, "volatile ");
6068 if (t
& VT_UNSIGNED
)
6069 pstrcat(buf
, buf_size
, "unsigned ");
6099 tstr
= "long double";
6101 pstrcat(buf
, buf_size
, tstr
);
6105 if (bt
== VT_STRUCT
)
6109 pstrcat(buf
, buf_size
, tstr
);
6110 v
= type
->ref
->v
& ~SYM_STRUCT
;
6111 if (v
>= SYM_FIRST_ANOM
)
6112 pstrcat(buf
, buf_size
, "<anonymous>");
6114 pstrcat(buf
, buf_size
, get_tok_str(v
, NULL
));
6118 type_to_str(buf
, buf_size
, &s
->type
, varstr
);
6119 pstrcat(buf
, buf_size
, "(");
6121 while (sa
!= NULL
) {
6122 type_to_str(buf1
, sizeof(buf1
), &sa
->type
, NULL
);
6123 pstrcat(buf
, buf_size
, buf1
);
6126 pstrcat(buf
, buf_size
, ", ");
6128 pstrcat(buf
, buf_size
, ")");
6132 pstrcpy(buf1
, sizeof(buf1
), "*");
6134 pstrcat(buf1
, sizeof(buf1
), varstr
);
6135 type_to_str(buf
, buf_size
, &s
->type
, buf1
);
6139 pstrcat(buf
, buf_size
, " ");
6140 pstrcat(buf
, buf_size
, varstr
);
6145 /* verify type compatibility to store vtop in 'dt' type, and generate
6147 static void gen_assign_cast(CType
*dt
)
6149 CType
*st
, *type1
, *type2
, tmp_type1
, tmp_type2
;
6150 char buf1
[256], buf2
[256];
6153 st
= &vtop
->type
; /* source type */
6154 dbt
= dt
->t
& VT_BTYPE
;
6155 sbt
= st
->t
& VT_BTYPE
;
6156 if (dt
->t
& VT_CONSTANT
)
6157 warning("assignment of read-only location");
6160 /* special cases for pointers */
6161 /* '0' can also be a pointer */
6162 if (is_null_pointer(vtop
))
6164 /* accept implicit pointer to integer cast with warning */
6165 if (is_integer_btype(sbt
)) {
6166 warning("assignment makes pointer from integer without a cast");
6169 type1
= pointed_type(dt
);
6170 /* a function is implicitely a function pointer */
6171 if (sbt
== VT_FUNC
) {
6172 if ((type1
->t
& VT_BTYPE
) != VT_VOID
&&
6173 !is_compatible_types(pointed_type(dt
), st
))
6180 type2
= pointed_type(st
);
6181 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
6182 (type2
->t
& VT_BTYPE
) == VT_VOID
) {
6183 /* void * can match anything */
6185 /* exact type match, except for unsigned */
6188 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6189 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6190 if (!is_compatible_types(&tmp_type1
, &tmp_type2
))
6193 /* check const and volatile */
6194 if ((!(type1
->t
& VT_CONSTANT
) && (type2
->t
& VT_CONSTANT
)) ||
6195 (!(type1
->t
& VT_VOLATILE
) && (type2
->t
& VT_VOLATILE
)))
6196 warning("assignment discards qualifiers from pointer target type");
6202 if (sbt
== VT_PTR
|| sbt
== VT_FUNC
) {
6203 warning("assignment makes integer from pointer without a cast");
6205 /* XXX: more tests */
6210 tmp_type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6211 tmp_type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6212 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
6214 type_to_str(buf1
, sizeof(buf1
), st
, NULL
);
6215 type_to_str(buf2
, sizeof(buf2
), dt
, NULL
);
6216 error("cannot cast '%s' to '%s'", buf1
, buf2
);
6224 /* store vtop in lvalue pushed on stack */
6227 int sbt
, dbt
, ft
, r
, t
, size
, align
, bit_size
, bit_pos
, rc
, delayed_cast
;
6229 ft
= vtop
[-1].type
.t
;
6230 sbt
= vtop
->type
.t
& VT_BTYPE
;
6231 dbt
= ft
& VT_BTYPE
;
6232 if (((sbt
== VT_INT
|| sbt
== VT_SHORT
) && dbt
== VT_BYTE
) ||
6233 (sbt
== VT_INT
&& dbt
== VT_SHORT
)) {
6234 /* optimize char/short casts */
6235 delayed_cast
= VT_MUSTCAST
;
6236 vtop
->type
.t
= ft
& VT_TYPE
;
6237 /* XXX: factorize */
6238 if (ft
& VT_CONSTANT
)
6239 warning("assignment of read-only location");
6242 if (!(ft
& VT_BITFIELD
))
6243 gen_assign_cast(&vtop
[-1].type
);
6246 if (sbt
== VT_STRUCT
) {
6247 /* if structure, only generate pointer */
6248 /* structure assignment : generate memcpy */
6249 /* XXX: optimize if small size */
6250 if (!nocode_wanted
) {
6251 size
= type_size(&vtop
->type
, &align
);
6253 vpush_global_sym(&func_old_type
, TOK_memcpy
);
6257 vtop
->type
.t
= VT_INT
;
6261 vtop
->type
.t
= VT_INT
;
6273 /* leave source on stack */
6274 } else if (ft
& VT_BITFIELD
) {
6275 /* bitfield store handling */
6276 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
6277 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
6278 /* remove bit field info to avoid loops */
6279 vtop
[-1].type
.t
= ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
6281 /* duplicate destination */
6283 vtop
[-1] = vtop
[-2];
6285 /* mask and shift source */
6286 vpushi((1 << bit_size
) - 1);
6290 /* load destination, mask and or with source */
6292 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
6298 #ifdef CONFIG_TCC_BCHECK
6299 /* bound check case */
6300 if (vtop
[-1].r
& VT_MUSTBOUND
) {
6306 if (!nocode_wanted
) {
6310 r
= gv(rc
); /* generate value */
6311 /* if lvalue was saved on stack, must read it */
6312 if ((vtop
[-1].r
& VT_VALMASK
) == VT_LLOCAL
) {
6314 t
= get_reg(RC_INT
);
6316 sv
.r
= VT_LOCAL
| VT_LVAL
;
6317 sv
.c
.ul
= vtop
[-1].c
.ul
;
6319 vtop
[-1].r
= t
| VT_LVAL
;
6322 /* two word case handling : store second register at word + 4 */
6323 if ((ft
& VT_BTYPE
) == VT_LLONG
) {
6325 /* convert to int to increment easily */
6326 vtop
->type
.t
= VT_INT
;
6332 /* XXX: it works because r2 is spilled last ! */
6333 store(vtop
->r2
, vtop
- 1);
6337 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
6338 vtop
->r
|= delayed_cast
;
6342 /* post defines POST/PRE add. c is the token ++ or -- */
6343 void inc(int post
, int c
)
6346 vdup(); /* save lvalue */
6348 gv_dup(); /* duplicate value */
6353 vpushi(c
- TOK_MID
);
6355 vstore(); /* store value */
6357 vpop(); /* if post op, return saved value */
6360 /* Parse GNUC __attribute__ extension. Currently, the following
6361 extensions are recognized:
6362 - aligned(n) : set data/function alignment.
6363 - packed : force data alignment to 1
6364 - section(x) : generate data/code in this section.
6365 - unused : currently ignored, but may be used someday.
6366 - regparm(n) : pass function parameters in registers (i386 only)
6368 static void parse_attribute(AttributeDef
*ad
)
6372 while (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
) {
6376 while (tok
!= ')') {
6377 if (tok
< TOK_IDENT
)
6378 expect("attribute name");
6386 expect("section name");
6387 ad
->section
= find_section(tcc_state
, (char *)tokc
.cstr
->data
);
6396 if (n
<= 0 || (n
& (n
- 1)) != 0)
6397 error("alignment must be a positive power of two");
6410 /* currently, no need to handle it because tcc does not
6411 track unused objects */
6415 /* currently, no need to handle it because tcc does not
6416 track unused objects */
6421 ad
->func_call
= FUNC_CDECL
;
6426 ad
->func_call
= FUNC_STDCALL
;
6428 #ifdef TCC_TARGET_I386
6438 ad
->func_call
= FUNC_FASTCALL1
+ n
- 1;
6444 ad
->func_call
= FUNC_FASTCALLW
;
6451 if (tcc_state
->warn_unsupported
)
6452 warning("'%s' attribute ignored", get_tok_str(t
, NULL
));
6453 /* skip parameters */
6454 /* XXX: skip parenthesis too */
6457 while (tok
!= ')' && tok
!= -1)
6472 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6473 static void struct_decl(CType
*type
, int u
)
6475 int a
, v
, size
, align
, maxalign
, c
, offset
;
6476 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
;
6477 Sym
*s
, *ss
, *ass
, **ps
;
6481 a
= tok
; /* save decl type */
6486 /* struct already defined ? return it */
6488 expect("struct/union/enum name");
6492 error("invalid type");
6499 /* we put an undefined size for struct/union */
6500 s
= sym_push(v
| SYM_STRUCT
, &type1
, 0, -1);
6501 s
->r
= 0; /* default alignment is zero as gcc */
6502 /* put struct/union/enum name in type */
6510 error("struct/union/enum already defined");
6511 /* cannot be empty */
6513 /* non empty enums are not allowed */
6514 if (a
== TOK_ENUM
) {
6518 expect("identifier");
6524 /* enum symbols have static storage */
6525 ss
= sym_push(v
, &int_type
, VT_CONST
, c
);
6526 ss
->type
.t
|= VT_STATIC
;
6531 /* NOTE: we accept a trailing comma */
6541 while (tok
!= '}') {
6542 parse_btype(&btype
, &ad
);
6548 type_decl(&type1
, &ad
, &v
, TYPE_DIRECT
| TYPE_ABSTRACT
);
6549 if (v
== 0 && (type1
.t
& VT_BTYPE
) != VT_STRUCT
)
6550 expect("identifier");
6551 if ((type1
.t
& VT_BTYPE
) == VT_FUNC
||
6552 (type1
.t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
| VT_INLINE
)))
6553 error("invalid type for '%s'",
6554 get_tok_str(v
, NULL
));
6558 bit_size
= expr_const();
6559 /* XXX: handle v = 0 case for messages */
6561 error("negative width in bit-field '%s'",
6562 get_tok_str(v
, NULL
));
6563 if (v
&& bit_size
== 0)
6564 error("zero width for bit-field '%s'",
6565 get_tok_str(v
, NULL
));
6567 size
= type_size(&type1
, &align
);
6569 if (align
< ad
.aligned
)
6571 } else if (ad
.packed
) {
6573 } else if (*tcc_state
->pack_stack_ptr
) {
6574 if (align
> *tcc_state
->pack_stack_ptr
)
6575 align
= *tcc_state
->pack_stack_ptr
;
6578 if (bit_size
>= 0) {
6579 bt
= type1
.t
& VT_BTYPE
;
6585 error("bitfields must have scalar type");
6587 if (bit_size
> bsize
) {
6588 error("width of '%s' exceeds its type",
6589 get_tok_str(v
, NULL
));
6590 } else if (bit_size
== bsize
) {
6591 /* no need for bit fields */
6593 } else if (bit_size
== 0) {
6594 /* XXX: what to do if only padding in a
6596 /* zero size: means to pad */
6600 /* we do not have enough room ? */
6601 if ((bit_pos
+ bit_size
) > bsize
)
6604 /* XXX: handle LSB first */
6605 type1
.t
|= VT_BITFIELD
|
6606 (bit_pos
<< VT_STRUCT_SHIFT
) |
6607 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
6608 bit_pos
+= bit_size
;
6613 if (v
!= 0 || (type1
.t
& VT_BTYPE
) == VT_STRUCT
) {
6614 /* add new memory data only if starting
6616 if (lbit_pos
== 0) {
6617 if (a
== TOK_STRUCT
) {
6618 c
= (c
+ align
- 1) & -align
;
6626 if (align
> maxalign
)
6630 printf("add field %s offset=%d",
6631 get_tok_str(v
, NULL
), offset
);
6632 if (type1
.t
& VT_BITFIELD
) {
6633 printf(" pos=%d size=%d",
6634 (type1
.t
>> VT_STRUCT_SHIFT
) & 0x3f,
6635 (type1
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
6640 if (v
== 0 && (type1
.t
& VT_BTYPE
) == VT_STRUCT
) {
6642 while ((ass
= ass
->next
) != NULL
) {
6643 ss
= sym_push(ass
->v
, &ass
->type
, 0, offset
+ ass
->c
);
6648 ss
= sym_push(v
| SYM_FIELD
, &type1
, 0, offset
);
6652 if (tok
== ';' || tok
== TOK_EOF
)
6659 /* store size and alignment */
6660 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
6666 /* return 0 if no type declaration. otherwise, return the basic type
6669 static int parse_btype(CType
*type
, AttributeDef
*ad
)
6671 int t
, u
, type_found
, typespec_found
;
6675 memset(ad
, 0, sizeof(AttributeDef
));
6682 /* currently, we really ignore extension */
6692 if ((t
& VT_BTYPE
) != 0)
6693 error("too many basic types");
6709 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
6710 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6711 } else if ((t
& VT_BTYPE
) == VT_LONG
) {
6712 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
6726 if ((t
& VT_BTYPE
) == VT_LONG
) {
6727 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6734 struct_decl(&type1
, VT_ENUM
);
6737 type
->ref
= type1
.ref
;
6741 struct_decl(&type1
, VT_STRUCT
);
6744 /* type modifiers */
6797 /* GNUC attribute */
6798 case TOK_ATTRIBUTE1
:
6799 case TOK_ATTRIBUTE2
:
6800 parse_attribute(ad
);
6807 parse_expr_type(&type1
);
6813 if (!s
|| !(s
->type
.t
& VT_TYPEDEF
))
6815 t
|= (s
->type
.t
& ~VT_TYPEDEF
);
6816 type
->ref
= s
->type
.ref
;
6823 if ((t
& (VT_SIGNED
|VT_UNSIGNED
)) == (VT_SIGNED
|VT_UNSIGNED
))
6824 error("signed and unsigned modifier");
6825 if (tcc_state
->char_is_unsigned
) {
6826 if ((t
& (VT_SIGNED
|VT_UNSIGNED
|VT_BTYPE
)) == VT_BYTE
)
6831 /* long is never used as type */
6832 if ((t
& VT_BTYPE
) == VT_LONG
)
6833 t
= (t
& ~VT_BTYPE
) | VT_INT
;
6838 /* convert a function parameter type (array to pointer and function to
6839 function pointer) */
6840 static inline void convert_parameter_type(CType
*pt
)
6842 /* remove const and volatile qualifiers (XXX: const could be used
6843 to indicate a const function parameter */
6844 pt
->t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6845 /* array must be transformed to pointer according to ANSI C */
6847 if ((pt
->t
& VT_BTYPE
) == VT_FUNC
) {
6852 static void post_type(CType
*type
, AttributeDef
*ad
)
6855 Sym
**plast
, *s
, *first
;
6860 /* function declaration */
6867 /* read param name and compute offset */
6868 if (l
!= FUNC_OLD
) {
6869 if (!parse_btype(&pt
, &ad1
)) {
6871 error("invalid type");
6878 if ((pt
.t
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
6880 type_decl(&pt
, &ad1
, &n
, TYPE_DIRECT
| TYPE_ABSTRACT
);
6881 if ((pt
.t
& VT_BTYPE
) == VT_VOID
)
6882 error("parameter declared as void");
6887 expect("identifier");
6891 convert_parameter_type(&pt
);
6892 s
= sym_push(n
| SYM_FIELD
, &pt
, 0, 0);
6898 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
6905 /* if no parameters, then old type prototype */
6909 t1
= type
->t
& VT_STORAGE
;
6910 /* NOTE: const is ignored in returned type as it has a special
6911 meaning in gcc / C++ */
6912 type
->t
&= ~(VT_STORAGE
| VT_CONSTANT
);
6913 post_type(type
, ad
);
6914 /* we push a anonymous symbol which will contain the function prototype */
6915 s
= sym_push(SYM_FIELD
, type
, ad
->func_call
, l
);
6917 type
->t
= t1
| VT_FUNC
;
6919 } else if (tok
== '[') {
6920 /* array definition */
6926 error("invalid array size");
6929 /* parse next post type */
6930 t1
= type
->t
& VT_STORAGE
;
6931 type
->t
&= ~VT_STORAGE
;
6932 post_type(type
, ad
);
6934 /* we push a anonymous symbol which will contain the array
6936 s
= sym_push(SYM_FIELD
, type
, 0, n
);
6937 type
->t
= t1
| VT_ARRAY
| VT_PTR
;
6942 /* Parse a type declaration (except basic type), and return the type
6943 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6944 expected. 'type' should contain the basic type. 'ad' is the
6945 attribute definition of the basic type. It can be modified by
6948 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
)
6951 CType type1
, *type2
;
6954 while (tok
== '*') {
6962 qualifiers
|= VT_CONSTANT
;
6967 qualifiers
|= VT_VOLATILE
;
6975 type
->t
|= qualifiers
;
6978 /* XXX: clarify attribute handling */
6979 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
6980 parse_attribute(ad
);
6982 /* recursive type */
6983 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6984 type1
.t
= 0; /* XXX: same as int */
6987 /* XXX: this is not correct to modify 'ad' at this point, but
6988 the syntax is not clear */
6989 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
6990 parse_attribute(ad
);
6991 type_decl(&type1
, ad
, v
, td
);
6994 /* type identifier */
6995 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
6999 if (!(td
& TYPE_ABSTRACT
))
7000 expect("identifier");
7004 post_type(type
, ad
);
7005 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7006 parse_attribute(ad
);
7009 /* append type at the end of type1 */
7022 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7023 static int lvalue_type(int t
)
7028 if (bt
== VT_BYTE
|| bt
== VT_BOOL
)
7030 else if (bt
== VT_SHORT
)
7034 if (t
& VT_UNSIGNED
)
7035 r
|= VT_LVAL_UNSIGNED
;
7039 /* indirection with full error checking and bound check */
7040 static void indir(void)
7042 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
7044 if ((vtop
->r
& VT_LVAL
) && !nocode_wanted
)
7046 vtop
->type
= *pointed_type(&vtop
->type
);
7047 /* an array is never an lvalue */
7048 if (!(vtop
->type
.t
& VT_ARRAY
)) {
7049 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7050 /* if bound checking, the referenced pointer must be checked */
7051 if (do_bounds_check
)
7052 vtop
->r
|= VT_MUSTBOUND
;
7056 /* pass a parameter to a function and do type checking and casting */
7057 static void gfunc_param_typed(Sym
*func
, Sym
*arg
)
7062 func_type
= func
->c
;
7063 if (func_type
== FUNC_OLD
||
7064 (func_type
== FUNC_ELLIPSIS
&& arg
== NULL
)) {
7065 /* default casting : only need to convert float to double */
7066 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FLOAT
) {
7070 } else if (arg
== NULL
) {
7071 error("too many arguments to function");
7074 type
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
7075 gen_assign_cast(&type
);
7079 /* parse an expression of the form '(type)' or '(expr)' and return its
7081 static void parse_expr_type(CType
*type
)
7087 if (parse_btype(type
, &ad
)) {
7088 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7095 static void parse_type(CType
*type
)
7100 if (!parse_btype(type
, &ad
)) {
7103 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7106 static void vpush_tokc(int t
)
7110 vsetc(&type
, VT_CONST
, &tokc
);
7113 static void unary(void)
7115 int n
, t
, align
, size
, r
;
7120 /* XXX: GCC 2.95.3 does not generate a table although it should be
7134 vpush_tokc(VT_INT
| VT_UNSIGNED
);
7138 vpush_tokc(VT_LLONG
);
7142 vpush_tokc(VT_LLONG
| VT_UNSIGNED
);
7146 vpush_tokc(VT_FLOAT
);
7150 vpush_tokc(VT_DOUBLE
);
7154 vpush_tokc(VT_LDOUBLE
);
7157 case TOK___FUNCTION__
:
7159 goto tok_identifier
;
7165 /* special function name identifier */
7166 len
= strlen(funcname
) + 1;
7167 /* generate char[len] type */
7172 vpush_ref(&type
, data_section
, data_section
->data_offset
, len
);
7173 ptr
= section_ptr_add(data_section
, len
);
7174 memcpy(ptr
, funcname
, len
);
7179 #ifdef TCC_TARGET_PE
7180 t
= VT_SHORT
| VT_UNSIGNED
;
7186 /* string parsing */
7189 if (tcc_state
->warn_write_strings
)
7194 memset(&ad
, 0, sizeof(AttributeDef
));
7195 decl_initializer_alloc(&type
, &ad
, VT_CONST
, 2, 0, 0);
7200 if (parse_btype(&type
, &ad
)) {
7201 type_decl(&type
, &ad
, &n
, TYPE_ABSTRACT
);
7203 /* check ISOC99 compound literal */
7205 /* data is allocated locally by default */
7210 /* all except arrays are lvalues */
7211 if (!(type
.t
& VT_ARRAY
))
7212 r
|= lvalue_type(type
.t
);
7213 memset(&ad
, 0, sizeof(AttributeDef
));
7214 decl_initializer_alloc(&type
, &ad
, r
, 1, 0, 0);
7219 } else if (tok
== '{') {
7220 /* save all registers */
7222 /* statement expression : we do not accept break/continue
7223 inside as GCC does */
7224 block(NULL
, NULL
, NULL
, NULL
, 0, 1);
7239 /* functions names must be treated as function pointers,
7240 except for unary '&' and sizeof. Since we consider that
7241 functions are not lvalues, we only have to handle it
7242 there and in function calls. */
7243 /* arrays can also be used although they are not lvalues */
7244 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
&&
7245 !(vtop
->type
.t
& VT_ARRAY
))
7247 mk_pointer(&vtop
->type
);
7253 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
)
7254 vtop
->c
.i
= !vtop
->c
.i
;
7255 else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
7256 vtop
->c
.i
= vtop
->c
.i
^ 1;
7258 vseti(VT_JMP
, gtst(1, 0));
7268 /* in order to force cast, we add zero */
7270 if ((vtop
->type
.t
& VT_BTYPE
) == VT_PTR
)
7271 error("pointer not accepted for unary plus");
7281 parse_expr_type(&type
);
7285 size
= type_size(&type
, &align
);
7286 if (t
== TOK_SIZEOF
) {
7288 error("sizeof applied to an incomplete type");
7295 case TOK_builtin_types_compatible_p
:
7304 type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7305 type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7306 vpushi(is_compatible_types(&type1
, &type2
));
7309 case TOK_builtin_constant_p
:
7311 int saved_nocode_wanted
, res
;
7314 saved_nocode_wanted
= nocode_wanted
;
7317 res
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
7319 nocode_wanted
= saved_nocode_wanted
;
7339 goto tok_identifier
;
7341 /* allow to take the address of a label */
7342 if (tok
< TOK_UIDENT
)
7343 expect("label identifier");
7344 s
= label_find(tok
);
7346 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
7348 if (s
->r
== LABEL_DECLARED
)
7349 s
->r
= LABEL_FORWARD
;
7352 s
->type
.t
= VT_VOID
;
7353 mk_pointer(&s
->type
);
7354 s
->type
.t
|= VT_STATIC
;
7356 vset(&s
->type
, VT_CONST
| VT_SYM
, 0);
7365 expect("identifier");
7369 error("'%s' undeclared", get_tok_str(t
, NULL
));
7370 /* for simple function calls, we tolerate undeclared
7371 external reference to int() function */
7372 if (tcc_state
->warn_implicit_function_declaration
)
7373 warning("implicit declaration of function '%s'",
7374 get_tok_str(t
, NULL
));
7375 s
= external_global_sym(t
, &func_old_type
, 0);
7377 if ((s
->type
.t
& (VT_STATIC
| VT_INLINE
| VT_BTYPE
)) ==
7378 (VT_STATIC
| VT_INLINE
| VT_FUNC
)) {
7379 /* if referencing an inline function, then we generate a
7380 symbol to it if not already done. It will have the
7381 effect to generate code for it at the end of the
7382 compilation unit. Inline function as always
7383 generated in the text section. */
7385 put_extern_sym(s
, text_section
, 0, 0);
7386 r
= VT_SYM
| VT_CONST
;
7390 vset(&s
->type
, r
, s
->c
);
7391 /* if forward reference, we must point to s */
7392 if (vtop
->r
& VT_SYM
) {
7399 /* post operations */
7401 if (tok
== TOK_INC
|| tok
== TOK_DEC
) {
7404 } else if (tok
== '.' || tok
== TOK_ARROW
) {
7406 if (tok
== TOK_ARROW
)
7411 /* expect pointer on structure */
7412 if ((vtop
->type
.t
& VT_BTYPE
) != VT_STRUCT
)
7413 expect("struct or union");
7417 while ((s
= s
->next
) != NULL
) {
7422 error("field not found");
7423 /* add field offset to pointer */
7424 vtop
->type
= char_pointer_type
; /* change type to 'char *' */
7427 /* change type to field type, and set to lvalue */
7428 vtop
->type
= s
->type
;
7429 /* an array is never an lvalue */
7430 if (!(vtop
->type
.t
& VT_ARRAY
)) {
7431 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7432 /* if bound checking, the referenced pointer must be checked */
7433 if (do_bounds_check
)
7434 vtop
->r
|= VT_MUSTBOUND
;
7437 } else if (tok
== '[') {
7443 } else if (tok
== '(') {
7449 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
) {
7450 /* pointer test (no array accepted) */
7451 if ((vtop
->type
.t
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
7452 vtop
->type
= *pointed_type(&vtop
->type
);
7453 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
)
7457 expect("function pointer");
7460 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
7462 /* get return type */
7465 sa
= s
->next
; /* first parameter */
7467 /* compute first implicit argument if a structure is returned */
7468 if ((s
->type
.t
& VT_BTYPE
) == VT_STRUCT
) {
7469 /* get some space for the returned structure */
7470 size
= type_size(&s
->type
, &align
);
7471 loc
= (loc
- size
) & -align
;
7473 ret
.r
= VT_LOCAL
| VT_LVAL
;
7474 /* pass it as 'int' to avoid structure arg passing
7476 vseti(VT_LOCAL
, loc
);
7482 /* return in register */
7483 if (is_float(ret
.type
.t
)) {
7486 if ((ret
.type
.t
& VT_BTYPE
) == VT_LLONG
)
7495 gfunc_param_typed(s
, sa
);
7505 error("too few arguments to function");
7507 if (!nocode_wanted
) {
7508 gfunc_call(nb_args
);
7510 vtop
-= (nb_args
+ 1);
7513 vsetc(&ret
.type
, ret
.r
, &ret
.c
);
7521 static void uneq(void)
7527 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
7528 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
7529 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
7544 static void expr_prod(void)
7549 while (tok
== '*' || tok
== '/' || tok
== '%') {
7557 static void expr_sum(void)
7562 while (tok
== '+' || tok
== '-') {
7570 static void expr_shift(void)
7575 while (tok
== TOK_SHL
|| tok
== TOK_SAR
) {
7583 static void expr_cmp(void)
7588 while ((tok
>= TOK_ULE
&& tok
<= TOK_GT
) ||
7589 tok
== TOK_ULT
|| tok
== TOK_UGE
) {
7597 static void expr_cmpeq(void)
7602 while (tok
== TOK_EQ
|| tok
== TOK_NE
) {
7610 static void expr_and(void)
7613 while (tok
== '&') {
7620 static void expr_xor(void)
7623 while (tok
== '^') {
7630 static void expr_or(void)
7633 while (tok
== '|') {
7640 /* XXX: fix this mess */
7641 static void expr_land_const(void)
7644 while (tok
== TOK_LAND
) {
7651 /* XXX: fix this mess */
7652 static void expr_lor_const(void)
7655 while (tok
== TOK_LOR
) {
7662 /* only used if non constant */
7663 static void expr_land(void)
7668 if (tok
== TOK_LAND
) {
7672 if (tok
!= TOK_LAND
) {
7682 static void expr_lor(void)
7687 if (tok
== TOK_LOR
) {
7691 if (tok
!= TOK_LOR
) {
7701 /* XXX: better constant handling */
7702 static void expr_eq(void)
7704 int tt
, u
, r1
, r2
, rc
, t1
, t2
, bt1
, bt2
;
7706 CType type
, type1
, type2
;
7715 if (tok
== ':' && gnu_ext
) {
7731 if (vtop
!= vstack
) {
7732 /* needed to avoid having different registers saved in
7734 if (is_float(vtop
->type
.t
))
7741 if (tok
== ':' && gnu_ext
) {
7749 sv
= *vtop
; /* save value to handle it later */
7750 vtop
--; /* no vpop so that FP stack is not flushed */
7758 bt1
= t1
& VT_BTYPE
;
7760 bt2
= t2
& VT_BTYPE
;
7761 /* cast operands to correct type according to ISOC rules */
7762 if (is_float(bt1
) || is_float(bt2
)) {
7763 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
7764 type
.t
= VT_LDOUBLE
;
7765 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
7770 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
7771 /* cast to biggest op */
7773 /* convert to unsigned if it does not fit in a long long */
7774 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
7775 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
7776 type
.t
|= VT_UNSIGNED
;
7777 } else if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
7778 /* XXX: test pointer compatibility */
7780 } else if (bt1
== VT_STRUCT
|| bt2
== VT_STRUCT
) {
7781 /* XXX: test structure compatibility */
7783 } else if (bt1
== VT_VOID
|| bt2
== VT_VOID
) {
7784 /* NOTE: as an extension, we accept void on only one side */
7787 /* integer operations */
7789 /* convert to unsigned if it does not fit in an integer */
7790 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
7791 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
7792 type
.t
|= VT_UNSIGNED
;
7795 /* now we convert second operand */
7798 if (is_float(type
.t
)) {
7800 } else if ((type
.t
& VT_BTYPE
) == VT_LLONG
) {
7801 /* for long longs, we use fixed registers to avoid having
7802 to handle a complicated move */
7807 /* this is horrible, but we must also convert first
7811 /* put again first value and cast it */
7822 static void gexpr(void)
7833 /* parse an expression and return its type without any side effect. */
7834 static void expr_type(CType
*type
)
7836 int saved_nocode_wanted
;
7838 saved_nocode_wanted
= nocode_wanted
;
7843 nocode_wanted
= saved_nocode_wanted
;
7846 /* parse a unary expression and return its type without any side
7848 static void unary_type(CType
*type
)
7860 /* parse a constant expression and return value in vtop. */
7861 static void expr_const1(void)
7870 /* parse an integer constant and return its value. */
7871 static int expr_const(void)
7875 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
7876 expect("constant expression");
7882 /* return the label token if current token is a label, otherwise
7884 static int is_label(void)
7888 /* fast test first */
7889 if (tok
< TOK_UIDENT
)
7891 /* no need to save tokc because tok is an identifier */
7898 unget_tok(last_tok
);
7903 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
7904 int case_reg
, int is_expr
)
7909 /* generate line number info */
7911 (last_line_num
!= file
->line_num
|| last_ind
!= ind
)) {
7912 put_stabn(N_SLINE
, 0, file
->line_num
, ind
- func_ind
);
7914 last_line_num
= file
->line_num
;
7918 /* default return value is (void) */
7920 vtop
->type
.t
= VT_VOID
;
7923 if (tok
== TOK_IF
) {
7930 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
7932 if (c
== TOK_ELSE
) {
7936 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
7937 gsym(d
); /* patch else jmp */
7940 } else if (tok
== TOK_WHILE
) {
7948 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
7952 } else if (tok
== '{') {
7956 /* record local declaration stack position */
7958 llabel
= local_label_stack
;
7959 /* handle local labels declarations */
7960 if (tok
== TOK_LABEL
) {
7963 if (tok
< TOK_UIDENT
)
7964 expect("label identifier");
7965 label_push(&local_label_stack
, tok
, LABEL_DECLARED
);
7975 while (tok
!= '}') {
7980 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
7983 /* pop locally defined labels */
7984 label_pop(&local_label_stack
, llabel
);
7985 /* pop locally defined symbols */
7986 sym_pop(&local_stack
, s
);
7988 } else if (tok
== TOK_RETURN
) {
7992 gen_assign_cast(&func_vt
);
7993 if ((func_vt
.t
& VT_BTYPE
) == VT_STRUCT
) {
7995 /* if returning structure, must copy it to implicit
7996 first pointer arg location */
7999 vset(&type
, VT_LOCAL
| VT_LVAL
, func_vc
);
8002 /* copy structure value to pointer */
8004 } else if (is_float(func_vt
.t
)) {
8009 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
8012 rsym
= gjmp(rsym
); /* jmp */
8013 } else if (tok
== TOK_BREAK
) {
8016 error("cannot break");
8017 *bsym
= gjmp(*bsym
);
8020 } else if (tok
== TOK_CONTINUE
) {
8023 error("cannot continue");
8024 *csym
= gjmp(*csym
);
8027 } else if (tok
== TOK_FOR
) {
8054 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8059 if (tok
== TOK_DO
) {
8064 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8075 if (tok
== TOK_SWITCH
) {
8079 /* XXX: other types than integer */
8080 case_reg
= gv(RC_INT
);
8084 b
= gjmp(0); /* jump to first case */
8086 block(&a
, csym
, &b
, &c
, case_reg
, 0);
8087 /* if no default, jmp after switch */
8095 if (tok
== TOK_CASE
) {
8102 if (gnu_ext
&& tok
== TOK_DOTS
) {
8106 warning("empty case range");
8108 /* since a case is like a label, we must skip it with a jmp */
8115 *case_sym
= gtst(1, 0);
8118 *case_sym
= gtst(1, 0);
8122 *case_sym
= gtst(1, *case_sym
);
8127 goto block_after_label
;
8129 if (tok
== TOK_DEFAULT
) {
8135 error("too many 'default'");
8138 goto block_after_label
;
8140 if (tok
== TOK_GOTO
) {
8142 if (tok
== '*' && gnu_ext
) {
8146 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
8149 } else if (tok
>= TOK_UIDENT
) {
8150 s
= label_find(tok
);
8151 /* put forward definition if needed */
8153 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
8155 if (s
->r
== LABEL_DECLARED
)
8156 s
->r
= LABEL_FORWARD
;
8158 /* label already defined */
8159 if (s
->r
& LABEL_FORWARD
)
8160 s
->next
= (void *)gjmp((long)s
->next
);
8162 gjmp_addr((long)s
->next
);
8165 expect("label identifier");
8168 } else if (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
) {
8176 if (s
->r
== LABEL_DEFINED
)
8177 error("duplicate label '%s'", get_tok_str(s
->v
, NULL
));
8178 gsym((long)s
->next
);
8179 s
->r
= LABEL_DEFINED
;
8181 s
= label_push(&global_label_stack
, b
, LABEL_DEFINED
);
8183 s
->next
= (void *)ind
;
8184 /* we accept this, but it is a mistake */
8187 warning("deprecated use of label at end of compound statement");
8191 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
8194 /* expression case */
8209 /* t is the array or struct type. c is the array or struct
8210 address. cur_index/cur_field is the pointer to the current
8211 value. 'size_only' is true if only size info is needed (only used
8213 static void decl_designator(CType
*type
, Section
*sec
, unsigned long c
,
8214 int *cur_index
, Sym
**cur_field
,
8218 int notfirst
, index
, index_last
, align
, l
, nb_elems
, elem_size
;
8224 if (gnu_ext
&& (l
= is_label()) != 0)
8226 while (tok
== '[' || tok
== '.') {
8228 if (!(type
->t
& VT_ARRAY
))
8229 expect("array type");
8232 index
= expr_const();
8233 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
8234 expect("invalid index");
8235 if (tok
== TOK_DOTS
&& gnu_ext
) {
8237 index_last
= expr_const();
8238 if (index_last
< 0 ||
8239 (s
->c
>= 0 && index_last
>= s
->c
) ||
8241 expect("invalid index");
8247 *cur_index
= index_last
;
8248 type
= pointed_type(type
);
8249 elem_size
= type_size(type
, &align
);
8250 c
+= index
* elem_size
;
8251 /* NOTE: we only support ranges for last designator */
8252 nb_elems
= index_last
- index
+ 1;
8253 if (nb_elems
!= 1) {
8262 if ((type
->t
& VT_BTYPE
) != VT_STRUCT
)
8263 expect("struct/union type");
8276 /* XXX: fix this mess by using explicit storage field */
8278 type1
.t
|= (type
->t
& ~VT_TYPE
);
8292 if (type
->t
& VT_ARRAY
) {
8294 type
= pointed_type(type
);
8295 c
+= index
* type_size(type
, &align
);
8299 error("too many field init");
8300 /* XXX: fix this mess by using explicit storage field */
8302 type1
.t
|= (type
->t
& ~VT_TYPE
);
8307 decl_initializer(type
, sec
, c
, 0, size_only
);
8309 /* XXX: make it more general */
8310 if (!size_only
&& nb_elems
> 1) {
8311 unsigned long c_end
;
8316 error("range init not supported yet for dynamic storage");
8317 c_end
= c
+ nb_elems
* elem_size
;
8318 if (c_end
> sec
->data_allocated
)
8319 section_realloc(sec
, c_end
);
8320 src
= sec
->data
+ c
;
8322 for(i
= 1; i
< nb_elems
; i
++) {
8324 memcpy(dst
, src
, elem_size
);
8330 #define EXPR_CONST 1
8333 /* store a value or an expression directly in global data or in local array */
8334 static void init_putv(CType
*type
, Section
*sec
, unsigned long c
,
8335 int v
, int expr_type
)
8337 int saved_global_expr
, bt
, bit_pos
, bit_size
;
8339 unsigned long long bit_mask
;
8347 /* compound literals must be allocated globally in this case */
8348 saved_global_expr
= global_expr
;
8351 global_expr
= saved_global_expr
;
8352 /* NOTE: symbols are accepted */
8353 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) != VT_CONST
)
8354 error("initializer element is not constant");
8362 dtype
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
8365 /* XXX: not portable */
8366 /* XXX: generate error if incorrect relocation */
8367 gen_assign_cast(&dtype
);
8368 bt
= type
->t
& VT_BTYPE
;
8369 ptr
= sec
->data
+ c
;
8370 /* XXX: make code faster ? */
8371 if (!(type
->t
& VT_BITFIELD
)) {
8376 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
8377 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
8378 bit_mask
= (1LL << bit_size
) - 1;
8380 if ((vtop
->r
& VT_SYM
) &&
8386 (bt
== VT_INT
&& bit_size
!= 32)))
8387 error("initializer element is not computable at load time");
8390 *(char *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8393 *(short *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8396 *(double *)ptr
= vtop
->c
.d
;
8399 *(long double *)ptr
= vtop
->c
.ld
;
8402 *(long long *)ptr
|= (vtop
->c
.ll
& bit_mask
) << bit_pos
;
8405 if (vtop
->r
& VT_SYM
) {
8406 greloc(sec
, vtop
->sym
, c
, R_DATA_32
);
8408 *(int *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8413 vset(&dtype
, VT_LOCAL
, c
);
8420 /* put zeros for variable based init */
8421 static void init_putz(CType
*t
, Section
*sec
, unsigned long c
, int size
)
8424 /* nothing to do because globals are already set to zero */
8426 vpush_global_sym(&func_old_type
, TOK_memset
);
8434 /* 't' contains the type and storage info. 'c' is the offset of the
8435 object in section 'sec'. If 'sec' is NULL, it means stack based
8436 allocation. 'first' is true if array '{' must be read (multi
8437 dimension implicit array init handling). 'size_only' is true if
8438 size only evaluation is wanted (only for arrays). */
8439 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
8440 int first
, int size_only
)
8442 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
8443 int size1
, align1
, expr_type
;
8447 if (type
->t
& VT_ARRAY
) {
8451 t1
= pointed_type(type
);
8452 size1
= type_size(t1
, &align1
);
8455 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
8461 /* only parse strings here if correct type (otherwise: handle
8462 them as ((w)char *) expressions */
8463 if ((tok
== TOK_LSTR
&&
8464 #ifdef TCC_TARGET_PE
8465 (t1
->t
& VT_BTYPE
) == VT_SHORT
&& (t1
->t
& VT_UNSIGNED
)) ||
8467 (t1
->t
& VT_BTYPE
) == VT_INT
) ||
8470 (t1
->t
& VT_BTYPE
) == VT_BYTE
)) {
8471 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8476 /* compute maximum number of chars wanted */
8478 cstr_len
= cstr
->size
;
8480 cstr_len
= cstr
->size
/ sizeof(nwchar_t
);
8483 if (n
>= 0 && nb
> (n
- array_length
))
8484 nb
= n
- array_length
;
8487 warning("initializer-string for array is too long");
8488 /* in order to go faster for common case (char
8489 string in global variable, we handle it
8491 if (sec
&& tok
== TOK_STR
&& size1
== 1) {
8492 memcpy(sec
->data
+ c
+ array_length
, cstr
->data
, nb
);
8496 ch
= ((unsigned char *)cstr
->data
)[i
];
8498 ch
= ((nwchar_t
*)cstr
->data
)[i
];
8499 init_putv(t1
, sec
, c
+ (array_length
+ i
) * size1
,
8507 /* only add trailing zero if enough storage (no
8508 warning in this case since it is standard) */
8509 if (n
< 0 || array_length
< n
) {
8511 init_putv(t1
, sec
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
8517 while (tok
!= '}') {
8518 decl_designator(type
, sec
, c
, &index
, NULL
, size_only
);
8519 if (n
>= 0 && index
>= n
)
8520 error("index too large");
8521 /* must put zero in holes (note that doing it that way
8522 ensures that it even works with designators) */
8523 if (!size_only
&& array_length
< index
) {
8524 init_putz(t1
, sec
, c
+ array_length
* size1
,
8525 (index
- array_length
) * size1
);
8528 if (index
> array_length
)
8529 array_length
= index
;
8530 /* special test for multi dimensional arrays (may not
8531 be strictly correct if designators are used at the
8533 if (index
>= n
&& no_oblock
)
8542 /* put zeros at the end */
8543 if (!size_only
&& n
>= 0 && array_length
< n
) {
8544 init_putz(t1
, sec
, c
+ array_length
* size1
,
8545 (n
- array_length
) * size1
);
8547 /* patch type size if needed */
8549 s
->c
= array_length
;
8550 } else if ((type
->t
& VT_BTYPE
) == VT_STRUCT
&&
8551 (sec
|| !first
|| tok
== '{')) {
8554 /* NOTE: the previous test is a specific case for automatic
8555 struct/union init */
8556 /* XXX: union needs only one init */
8558 /* XXX: this test is incorrect for local initializers
8559 beginning with ( without {. It would be much more difficult
8560 to do it correctly (ideally, the expression parser should
8561 be used in all cases) */
8567 while (tok
== '(') {
8571 if (!parse_btype(&type1
, &ad1
))
8573 type_decl(&type1
, &ad1
, &n
, TYPE_ABSTRACT
);
8575 if (!is_assignable_types(type
, &type1
))
8576 error("invalid type for cast");
8581 if (first
|| tok
== '{') {
8590 while (tok
!= '}') {
8591 decl_designator(type
, sec
, c
, NULL
, &f
, size_only
);
8593 if (!size_only
&& array_length
< index
) {
8594 init_putz(type
, sec
, c
+ array_length
,
8595 index
- array_length
);
8597 index
= index
+ type_size(&f
->type
, &align1
);
8598 if (index
> array_length
)
8599 array_length
= index
;
8601 if (no_oblock
&& f
== NULL
)
8607 /* put zeros at the end */
8608 if (!size_only
&& array_length
< n
) {
8609 init_putz(type
, sec
, c
+ array_length
,
8618 } else if (tok
== '{') {
8620 decl_initializer(type
, sec
, c
, first
, size_only
);
8622 } else if (size_only
) {
8623 /* just skip expression */
8625 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
8629 else if (tok
== ')')
8634 /* currently, we always use constant expression for globals
8635 (may change for scripting case) */
8636 expr_type
= EXPR_CONST
;
8638 expr_type
= EXPR_ANY
;
8639 init_putv(type
, sec
, c
, 0, expr_type
);
8643 /* parse an initializer for type 't' if 'has_init' is non zero, and
8644 allocate space in local or global data space ('r' is either
8645 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8646 variable 'v' of scope 'scope' is declared before initializers are
8647 parsed. If 'v' is zero, then a reference to the new object is put
8648 in the value stack. If 'has_init' is 2, a special parsing is done
8649 to handle string constants. */
8650 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
8651 int has_init
, int v
, int scope
)
8653 int size
, align
, addr
, data_offset
;
8655 ParseState saved_parse_state
;
8656 TokenString init_str
;
8659 size
= type_size(type
, &align
);
8660 /* If unknown size, we must evaluate it before
8661 evaluating initializers because
8662 initializers can generate global data too
8663 (e.g. string pointers or ISOC99 compound
8664 literals). It also simplifies local
8665 initializers handling */
8666 tok_str_new(&init_str
);
8669 error("unknown type size");
8670 /* get all init string */
8671 if (has_init
== 2) {
8672 /* only get strings */
8673 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8674 tok_str_add_tok(&init_str
);
8679 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
8681 error("unexpected end of file in initializer");
8682 tok_str_add_tok(&init_str
);
8685 else if (tok
== '}') {
8693 tok_str_add(&init_str
, -1);
8694 tok_str_add(&init_str
, 0);
8697 save_parse_state(&saved_parse_state
);
8699 macro_ptr
= init_str
.str
;
8701 decl_initializer(type
, NULL
, 0, 1, 1);
8702 /* prepare second initializer parsing */
8703 macro_ptr
= init_str
.str
;
8706 /* if still unknown size, error */
8707 size
= type_size(type
, &align
);
8709 error("unknown type size");
8711 /* take into account specified alignment if bigger */
8713 if (ad
->aligned
> align
)
8714 align
= ad
->aligned
;
8715 } else if (ad
->packed
) {
8718 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
8720 if (do_bounds_check
&& (type
->t
& VT_ARRAY
))
8722 loc
= (loc
- size
) & -align
;
8724 /* handles bounds */
8725 /* XXX: currently, since we do only one pass, we cannot track
8726 '&' operators, so we add only arrays */
8727 if (do_bounds_check
&& (type
->t
& VT_ARRAY
)) {
8728 unsigned long *bounds_ptr
;
8729 /* add padding between regions */
8731 /* then add local bound info */
8732 bounds_ptr
= section_ptr_add(lbounds_section
, 2 * sizeof(unsigned long));
8733 bounds_ptr
[0] = addr
;
8734 bounds_ptr
[1] = size
;
8737 /* local variable */
8738 sym_push(v
, type
, r
, addr
);
8740 /* push local reference */
8741 vset(type
, r
, addr
);
8747 if (v
&& scope
== VT_CONST
) {
8748 /* see if the symbol was already defined */
8751 if (!is_compatible_types(&sym
->type
, type
))
8752 error("incompatible types for redefinition of '%s'",
8753 get_tok_str(v
, NULL
));
8754 if (sym
->type
.t
& VT_EXTERN
) {
8755 /* if the variable is extern, it was not allocated */
8756 sym
->type
.t
&= ~VT_EXTERN
;
8757 /* set array size if it was ommited in extern
8759 if ((sym
->type
.t
& VT_ARRAY
) &&
8760 sym
->type
.ref
->c
< 0 &&
8762 sym
->type
.ref
->c
= type
->ref
->c
;
8764 /* we accept several definitions of the same
8765 global variable. this is tricky, because we
8766 must play with the SHN_COMMON type of the symbol */
8767 /* XXX: should check if the variable was already
8768 initialized. It is incorrect to initialized it
8770 /* no init data, we won't add more to the symbol */
8777 /* allocate symbol in corresponding section */
8782 else if (tcc_state
->nocommon
)
8786 data_offset
= sec
->data_offset
;
8787 data_offset
= (data_offset
+ align
- 1) & -align
;
8789 /* very important to increment global pointer at this time
8790 because initializers themselves can create new initializers */
8791 data_offset
+= size
;
8792 /* add padding if bound check */
8793 if (do_bounds_check
)
8795 sec
->data_offset
= data_offset
;
8796 /* allocate section space to put the data */
8797 if (sec
->sh_type
!= SHT_NOBITS
&&
8798 data_offset
> sec
->data_allocated
)
8799 section_realloc(sec
, data_offset
);
8800 /* align section if needed */
8801 if (align
> sec
->sh_addralign
)
8802 sec
->sh_addralign
= align
;
8804 addr
= 0; /* avoid warning */
8808 if (scope
== VT_CONST
) {
8813 sym
= sym_push(v
, type
, r
| VT_SYM
, 0);
8815 /* update symbol definition */
8817 put_extern_sym(sym
, sec
, addr
, size
);
8820 /* put a common area */
8821 put_extern_sym(sym
, NULL
, align
, size
);
8822 /* XXX: find a nicer way */
8823 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
8824 esym
->st_shndx
= SHN_COMMON
;
8829 /* push global reference */
8830 sym
= get_sym_ref(type
, sec
, addr
, size
);
8832 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
8836 /* handles bounds now because the symbol must be defined
8837 before for the relocation */
8838 if (do_bounds_check
) {
8839 unsigned long *bounds_ptr
;
8841 greloc(bounds_section
, sym
, bounds_section
->data_offset
, R_DATA_32
);
8842 /* then add global bound info */
8843 bounds_ptr
= section_ptr_add(bounds_section
, 2 * sizeof(long));
8844 bounds_ptr
[0] = 0; /* relocated */
8845 bounds_ptr
[1] = size
;
8849 decl_initializer(type
, sec
, addr
, 1, 0);
8850 /* restore parse state if needed */
8852 tok_str_free(init_str
.str
);
8853 restore_parse_state(&saved_parse_state
);
8859 void put_func_debug(Sym
*sym
)
8864 /* XXX: we put here a dummy type */
8865 snprintf(buf
, sizeof(buf
), "%s:%c1",
8866 funcname
, sym
->type
.t
& VT_STATIC
? 'f' : 'F');
8867 put_stabs_r(buf
, N_FUN
, 0, file
->line_num
, 0,
8868 cur_text_section
, sym
->c
);
8873 /* parse an old style function declaration list */
8874 /* XXX: check multiple parameter */
8875 static void func_decl_list(Sym
*func_sym
)
8882 /* parse each declaration */
8883 while (tok
!= '{' && tok
!= ';' && tok
!= ',' && tok
!= TOK_EOF
) {
8884 if (!parse_btype(&btype
, &ad
))
8885 expect("declaration list");
8886 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
8887 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
8889 /* we accept no variable after */
8893 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
8894 /* find parameter in function parameter list */
8897 if ((s
->v
& ~SYM_FIELD
) == v
)
8901 error("declaration for parameter '%s' but no such parameter",
8902 get_tok_str(v
, NULL
));
8904 /* check that no storage specifier except 'register' was given */
8905 if (type
.t
& VT_STORAGE
)
8906 error("storage class specified for '%s'", get_tok_str(v
, NULL
));
8907 convert_parameter_type(&type
);
8908 /* we can add the type (NOTE: it could be local to the function) */
8910 /* accept other parameters */
8921 /* parse a function defined by symbol 'sym' and generate its code in
8922 'cur_text_section' */
8923 static void gen_function(Sym
*sym
)
8925 ind
= cur_text_section
->data_offset
;
8926 /* NOTE: we patch the symbol size later */
8927 put_extern_sym(sym
, cur_text_section
, ind
, 0);
8928 funcname
= get_tok_str(sym
->v
, NULL
);
8930 /* put debug symbol */
8932 put_func_debug(sym
);
8933 /* push a dummy symbol to enable local sym storage */
8934 sym_push2(&local_stack
, SYM_FIELD
, 0, 0);
8935 gfunc_prolog(&sym
->type
);
8937 block(NULL
, NULL
, NULL
, NULL
, 0, 0);
8940 cur_text_section
->data_offset
= ind
;
8941 label_pop(&global_label_stack
, NULL
);
8942 sym_pop(&local_stack
, NULL
); /* reset local stack */
8943 /* end of function */
8944 /* patch symbol size */
8945 ((Elf32_Sym
*)symtab_section
->data
)[sym
->c
].st_size
=
8948 put_stabn(N_FUN
, 0, 0, ind
- func_ind
);
8950 funcname
= ""; /* for safety */
8951 func_vt
.t
= VT_VOID
; /* for safety */
8952 ind
= 0; /* for safety */
8955 static void gen_inline_functions(void)
8959 int *str
, inline_generated
;
8961 /* iterate while inline function are referenced */
8963 inline_generated
= 0;
8964 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
8966 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
8967 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
8968 (VT_STATIC
| VT_INLINE
) &&
8970 /* the function was used: generate its code and
8971 convert it to a normal function */
8972 str
= (int *)sym
->r
;
8973 sym
->r
= VT_SYM
| VT_CONST
;
8974 type
->t
&= ~VT_INLINE
;
8978 cur_text_section
= text_section
;
8980 macro_ptr
= NULL
; /* fail safe */
8983 inline_generated
= 1;
8986 if (!inline_generated
)
8990 /* free all remaining inline function tokens */
8991 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
8993 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
8994 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
8995 (VT_STATIC
| VT_INLINE
)) {
8996 str
= (int *)sym
->r
;
8998 sym
->r
= 0; /* fail safe */
9003 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9004 static void decl(int l
)
9012 if (!parse_btype(&btype
, &ad
)) {
9013 /* skip redundant ';' */
9014 /* XXX: find more elegant solution */
9019 if (l
== VT_CONST
&&
9020 (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
)) {
9021 /* global asm block */
9025 /* special test for old K&R protos without explicit int
9026 type. Only accepted when defining global data */
9027 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
9031 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
9032 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
9034 /* we accept no variable after */
9038 while (1) { /* iterate thru each declaration */
9040 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
9044 type_to_str(buf
, sizeof(buf
), &type
, get_tok_str(v
, NULL
));
9045 printf("type = '%s'\n", buf
);
9048 if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9049 /* if old style function prototype, we accept a
9052 if (sym
->c
== FUNC_OLD
)
9053 func_decl_list(sym
);
9058 error("cannot use local functions");
9059 if ((type
.t
& VT_BTYPE
) != VT_FUNC
)
9060 expect("function definition");
9062 /* reject abstract declarators in function definition */
9064 while ((sym
= sym
->next
) != NULL
)
9065 if (!(sym
->v
& ~SYM_FIELD
))
9066 expect("identifier");
9068 /* XXX: cannot do better now: convert extern line to static inline */
9069 if ((type
.t
& (VT_EXTERN
| VT_INLINE
)) == (VT_EXTERN
| VT_INLINE
))
9070 type
.t
= (type
.t
& ~VT_EXTERN
) | VT_STATIC
;
9074 if ((sym
->type
.t
& VT_BTYPE
) != VT_FUNC
)
9076 /* specific case: if not func_call defined, we put
9077 the one of the prototype */
9078 /* XXX: should have default value */
9079 if (sym
->type
.ref
->r
!= FUNC_CDECL
&&
9080 type
.ref
->r
== FUNC_CDECL
)
9081 type
.ref
->r
= sym
->type
.ref
->r
;
9082 if (!is_compatible_types(&sym
->type
, &type
)) {
9084 error("incompatible types for redefinition of '%s'",
9085 get_tok_str(v
, NULL
));
9087 /* if symbol is already defined, then put complete type */
9090 /* put function symbol */
9091 sym
= global_identifier_push(v
, type
.t
, 0);
9092 sym
->type
.ref
= type
.ref
;
9095 /* static inline functions are just recorded as a kind
9096 of macro. Their code will be emitted at the end of
9097 the compilation unit only if they are used */
9098 if ((type
.t
& (VT_INLINE
| VT_STATIC
)) ==
9099 (VT_INLINE
| VT_STATIC
)) {
9100 TokenString func_str
;
9103 tok_str_new(&func_str
);
9109 error("unexpected end of file");
9110 tok_str_add_tok(&func_str
);
9115 } else if (t
== '}') {
9117 if (block_level
== 0)
9121 tok_str_add(&func_str
, -1);
9122 tok_str_add(&func_str
, 0);
9123 sym
->r
= (int)func_str
.str
;
9125 /* compute text section */
9126 cur_text_section
= ad
.section
;
9127 if (!cur_text_section
)
9128 cur_text_section
= text_section
;
9129 sym
->r
= VT_SYM
| VT_CONST
;
9131 #ifdef TCC_TARGET_PE
9133 ((Elf32_Sym
*)symtab_section
->data
)[sym
->c
].st_other
|= 1;
9139 if (btype
.t
& VT_TYPEDEF
) {
9140 /* save typedefed type */
9141 /* XXX: test storage specifiers ? */
9142 sym
= sym_push(v
, &type
, 0, 0);
9143 sym
->type
.t
|= VT_TYPEDEF
;
9144 } else if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9145 /* external function definition */
9146 /* specific case for func_call attribute */
9148 type
.ref
->r
= ad
.func_call
;
9149 external_sym(v
, &type
, 0);
9151 /* not lvalue if array */
9153 if (!(type
.t
& VT_ARRAY
))
9154 r
|= lvalue_type(type
.t
);
9155 has_init
= (tok
== '=');
9156 if ((btype
.t
& VT_EXTERN
) ||
9157 ((type
.t
& VT_ARRAY
) && (type
.t
& VT_STATIC
) &&
9158 !has_init
&& l
== VT_CONST
&& type
.ref
->c
< 0)) {
9159 /* external variable */
9160 /* NOTE: as GCC, uninitialized global static
9161 arrays of null size are considered as
9163 external_sym(v
, &type
, r
);
9165 if (type
.t
& VT_STATIC
)
9171 decl_initializer_alloc(&type
, &ad
, r
,
9185 /* better than nothing, but needs extension to handle '-E' option
9187 static void preprocess_init(TCCState
*s1
)
9189 s1
->include_stack_ptr
= s1
->include_stack
;
9190 /* XXX: move that before to avoid having to initialize
9191 file->ifdef_stack_ptr ? */
9192 s1
->ifdef_stack_ptr
= s1
->ifdef_stack
;
9193 file
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
9195 /* XXX: not ANSI compliant: bound checking says error */
9197 s1
->pack_stack
[0] = 0;
9198 s1
->pack_stack_ptr
= s1
->pack_stack
;
9201 /* compile the C file opened in 'file'. Return non zero if errors. */
9202 static int tcc_compile(TCCState
*s1
)
9206 volatile int section_sym
;
9209 printf("%s: **** new file\n", file
->filename
);
9211 preprocess_init(s1
);
9214 anon_sym
= SYM_FIRST_ANOM
;
9216 /* file info: full path + filename */
9217 section_sym
= 0; /* avoid warning */
9219 section_sym
= put_elf_sym(symtab_section
, 0, 0,
9220 ELF32_ST_INFO(STB_LOCAL
, STT_SECTION
), 0,
9221 text_section
->sh_num
, NULL
);
9222 getcwd(buf
, sizeof(buf
));
9223 pstrcat(buf
, sizeof(buf
), "/");
9224 put_stabs_r(buf
, N_SO
, 0, 0,
9225 text_section
->data_offset
, text_section
, section_sym
);
9226 put_stabs_r(file
->filename
, N_SO
, 0, 0,
9227 text_section
->data_offset
, text_section
, section_sym
);
9229 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9230 symbols can be safely used */
9231 put_elf_sym(symtab_section
, 0, 0,
9232 ELF32_ST_INFO(STB_LOCAL
, STT_FILE
), 0,
9233 SHN_ABS
, file
->filename
);
9235 /* define some often used types */
9236 int_type
.t
= VT_INT
;
9238 char_pointer_type
.t
= VT_BYTE
;
9239 mk_pointer(&char_pointer_type
);
9241 func_old_type
.t
= VT_FUNC
;
9242 func_old_type
.ref
= sym_push(SYM_FIELD
, &int_type
, FUNC_CDECL
, FUNC_OLD
);
9245 /* define 'void *alloca(unsigned int)' builtin function */
9250 sym
= sym_push(p
, mk_pointer(VT_VOID
), FUNC_CDECL
, FUNC_NEW
);
9251 s1
= sym_push(SYM_FIELD
, VT_UNSIGNED
| VT_INT
, 0, 0);
9254 sym_push(TOK_alloca
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), VT_CONST
, 0);
9258 define_start
= define_stack
;
9260 if (setjmp(s1
->error_jmp_buf
) == 0) {
9262 s1
->error_set_jmp_enabled
= 1;
9264 ch
= file
->buf_ptr
[0];
9265 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
9266 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
;
9270 expect("declaration");
9272 /* end of translation unit info */
9274 put_stabs_r(NULL
, N_SO
, 0, 0,
9275 text_section
->data_offset
, text_section
, section_sym
);
9278 s1
->error_set_jmp_enabled
= 0;
9280 /* reset define stack, but leave -Dsymbols (may be incorrect if
9281 they are undefined) */
9282 free_defines(define_start
);
9284 gen_inline_functions();
9286 sym_pop(&global_stack
, NULL
);
9288 return s1
->nb_errors
!= 0 ? -1 : 0;
9291 /* Preprocess the current file */
9292 /* XXX: add line and file infos, add options to preserve spaces */
9293 static int tcc_preprocess(TCCState
*s1
)
9298 preprocess_init(s1
);
9300 define_start
= define_stack
;
9302 ch
= file
->buf_ptr
[0];
9303 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
9304 parse_flags
= PARSE_FLAG_ASM_COMMENTS
| PARSE_FLAG_PREPROCESS
|
9305 PARSE_FLAG_LINEFEED
;
9311 if (!last_is_space
) {
9312 fputc(' ', s1
->outfile
);
9314 fputs(get_tok_str(tok
, &tokc
), s1
->outfile
);
9315 if (tok
== TOK_LINEFEED
) {
9317 /* XXX: suppress that hack */
9318 parse_flags
&= ~PARSE_FLAG_LINEFEED
;
9320 parse_flags
|= PARSE_FLAG_LINEFEED
;
9327 free_defines(define_start
);
9333 int tcc_compile_string(TCCState
*s
, const char *str
)
9335 BufferedFile bf1
, *bf
= &bf1
;
9339 /* init file structure */
9341 /* XXX: avoid copying */
9343 buf
= tcc_malloc(len
+ 1);
9346 memcpy(buf
, str
, len
);
9349 bf
->buf_end
= buf
+ len
;
9350 pstrcpy(bf
->filename
, sizeof(bf
->filename
), "<string>");
9354 ret
= tcc_compile(s
);
9358 /* currently, no need to close */
9363 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9364 void tcc_define_symbol(TCCState
*s1
, const char *sym
, const char *value
)
9366 BufferedFile bf1
, *bf
= &bf1
;
9368 pstrcpy(bf
->buffer
, IO_BUF_SIZE
, sym
);
9369 pstrcat(bf
->buffer
, IO_BUF_SIZE
, " ");
9373 pstrcat(bf
->buffer
, IO_BUF_SIZE
, value
);
9375 /* init file structure */
9377 bf
->buf_ptr
= bf
->buffer
;
9378 bf
->buf_end
= bf
->buffer
+ strlen(bf
->buffer
);
9379 *bf
->buf_end
= CH_EOB
;
9380 bf
->filename
[0] = '\0';
9384 s1
->include_stack_ptr
= s1
->include_stack
;
9386 /* parse with define parser */
9387 ch
= file
->buf_ptr
[0];
9393 /* undefine a preprocessor symbol */
9394 void tcc_undefine_symbol(TCCState
*s1
, const char *sym
)
9398 ts
= tok_alloc(sym
, strlen(sym
));
9399 s
= define_find(ts
->tok
);
9400 /* undefine symbol by putting an invalid name */
9405 #ifdef CONFIG_TCC_ASM
9407 #ifdef TCC_TARGET_I386
9408 #include "i386-asm.c"
9413 static void asm_instr(void)
9415 error("inline asm() not supported");
9417 static void asm_global_instr(void)
9419 error("inline asm() not supported");
9425 #ifdef TCC_TARGET_COFF
9426 #include "tcccoff.c"
9429 #ifdef TCC_TARGET_PE
9433 /* print the position in the source file of PC value 'pc' by reading
9434 the stabs debug information */
9435 static void rt_printline(unsigned long wanted_pc
)
9437 Stab_Sym
*sym
, *sym_end
;
9438 char func_name
[128], last_func_name
[128];
9439 unsigned long func_addr
, last_pc
, pc
;
9440 const char *incl_files
[INCLUDE_STACK_SIZE
];
9441 int incl_index
, len
, last_line_num
, i
;
9442 const char *str
, *p
;
9444 fprintf(stderr
, "0x%08lx:", wanted_pc
);
9446 func_name
[0] = '\0';
9449 last_func_name
[0] = '\0';
9450 last_pc
= 0xffffffff;
9452 sym
= (Stab_Sym
*)stab_section
->data
+ 1;
9453 sym_end
= (Stab_Sym
*)(stab_section
->data
+ stab_section
->data_offset
);
9454 while (sym
< sym_end
) {
9455 switch(sym
->n_type
) {
9456 /* function start or end */
9458 if (sym
->n_strx
== 0) {
9459 /* we test if between last line and end of function */
9460 pc
= sym
->n_value
+ func_addr
;
9461 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
9463 func_name
[0] = '\0';
9466 str
= stabstr_section
->data
+ sym
->n_strx
;
9467 p
= strchr(str
, ':');
9469 pstrcpy(func_name
, sizeof(func_name
), str
);
9472 if (len
> sizeof(func_name
) - 1)
9473 len
= sizeof(func_name
) - 1;
9474 memcpy(func_name
, str
, len
);
9475 func_name
[len
] = '\0';
9477 func_addr
= sym
->n_value
;
9480 /* line number info */
9482 pc
= sym
->n_value
+ func_addr
;
9483 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
9486 last_line_num
= sym
->n_desc
;
9488 strcpy(last_func_name
, func_name
);
9492 str
= stabstr_section
->data
+ sym
->n_strx
;
9494 if (incl_index
< INCLUDE_STACK_SIZE
) {
9495 incl_files
[incl_index
++] = str
;
9503 if (sym
->n_strx
== 0) {
9504 incl_index
= 0; /* end of translation unit */
9506 str
= stabstr_section
->data
+ sym
->n_strx
;
9507 /* do not add path */
9509 if (len
> 0 && str
[len
- 1] != '/')
9517 /* second pass: we try symtab symbols (no line number info) */
9520 Elf32_Sym
*sym
, *sym_end
;
9523 sym_end
= (Elf32_Sym
*)(symtab_section
->data
+ symtab_section
->data_offset
);
9524 for(sym
= (Elf32_Sym
*)symtab_section
->data
+ 1;
9527 type
= ELF32_ST_TYPE(sym
->st_info
);
9528 if (type
== STT_FUNC
) {
9529 if (wanted_pc
>= sym
->st_value
&&
9530 wanted_pc
< sym
->st_value
+ sym
->st_size
) {
9531 pstrcpy(last_func_name
, sizeof(last_func_name
),
9532 strtab_section
->data
+ sym
->st_name
);
9538 /* did not find any info: */
9539 fprintf(stderr
, " ???\n");
9542 if (last_func_name
[0] != '\0') {
9543 fprintf(stderr
, " %s()", last_func_name
);
9545 if (incl_index
> 0) {
9546 fprintf(stderr
, " (%s:%d",
9547 incl_files
[incl_index
- 1], last_line_num
);
9548 for(i
= incl_index
- 2; i
>= 0; i
--)
9549 fprintf(stderr
, ", included from %s", incl_files
[i
]);
9550 fprintf(stderr
, ")");
9552 fprintf(stderr
, "\n");
9555 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
9559 /* fix for glibc 2.1 */
9565 /* return the PC at frame level 'level'. Return non zero if not found */
9566 static int rt_get_caller_pc(unsigned long *paddr
,
9567 ucontext_t
*uc
, int level
)
9573 #if defined(__FreeBSD__)
9574 *paddr
= uc
->uc_mcontext
.mc_eip
;
9575 #elif defined(__dietlibc__)
9576 *paddr
= uc
->uc_mcontext
.eip
;
9578 *paddr
= uc
->uc_mcontext
.gregs
[REG_EIP
];
9582 #if defined(__FreeBSD__)
9583 fp
= uc
->uc_mcontext
.mc_ebp
;
9584 #elif defined(__dietlibc__)
9585 fp
= uc
->uc_mcontext
.ebp
;
9587 fp
= uc
->uc_mcontext
.gregs
[REG_EBP
];
9589 for(i
=1;i
<level
;i
++) {
9590 /* XXX: check address validity with program info */
9591 if (fp
<= 0x1000 || fp
>= 0xc0000000)
9593 fp
= ((unsigned long *)fp
)[0];
9595 *paddr
= ((unsigned long *)fp
)[1];
9601 #warning add arch specific rt_get_caller_pc()
9603 static int rt_get_caller_pc(unsigned long *paddr
,
9604 ucontext_t
*uc
, int level
)
9610 /* emit a run time error at position 'pc' */
9611 void rt_error(ucontext_t
*uc
, const char *fmt
, ...)
9618 fprintf(stderr
, "Runtime error: ");
9619 vfprintf(stderr
, fmt
, ap
);
9620 fprintf(stderr
, "\n");
9621 for(i
=0;i
<num_callers
;i
++) {
9622 if (rt_get_caller_pc(&pc
, uc
, i
) < 0)
9625 fprintf(stderr
, "at ");
9627 fprintf(stderr
, "by ");
9634 /* signal handler for fatal errors */
9635 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
9637 ucontext_t
*uc
= puc
;
9641 switch(siginf
->si_code
) {
9644 rt_error(uc
, "division by zero");
9647 rt_error(uc
, "floating point exception");
9653 if (rt_bound_error_msg
&& *rt_bound_error_msg
)
9654 rt_error(uc
, *rt_bound_error_msg
);
9656 rt_error(uc
, "dereferencing invalid pointer");
9659 rt_error(uc
, "illegal instruction");
9662 rt_error(uc
, "abort() called");
9665 rt_error(uc
, "caught signal %d", signum
);
9672 /* do all relocations (needed before using tcc_get_symbol()) */
9673 int tcc_relocate(TCCState
*s1
)
9680 #ifdef TCC_TARGET_PE
9683 tcc_add_runtime(s1
);
9686 relocate_common_syms();
9688 tcc_add_linker_symbols(s1
);
9690 build_got_entries(s1
);
9692 /* compute relocation address : section are relocated in place. We
9693 also alloc the bss space */
9694 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9695 s
= s1
->sections
[i
];
9696 if (s
->sh_flags
& SHF_ALLOC
) {
9697 if (s
->sh_type
== SHT_NOBITS
)
9698 s
->data
= tcc_mallocz(s
->data_offset
);
9699 s
->sh_addr
= (unsigned long)s
->data
;
9703 relocate_syms(s1
, 1);
9705 if (s1
->nb_errors
!= 0)
9708 /* relocate each section */
9709 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9710 s
= s1
->sections
[i
];
9712 relocate_section(s1
, s
);
9715 /* mark executable sections as executable in memory */
9716 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9717 s
= s1
->sections
[i
];
9718 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_EXECINSTR
)) ==
9719 (SHF_ALLOC
| SHF_EXECINSTR
)) {
9723 VirtualProtect(s
->data
, s
->data_offset
,
9724 PAGE_EXECUTE_READWRITE
, &old_protect
);
9728 unsigned long start
, end
;
9729 start
= (unsigned long)(s
->data
) & ~(PAGESIZE
- 1);
9730 end
= (unsigned long)(s
->data
+ s
->data_offset
);
9731 end
= (end
+ PAGESIZE
- 1) & ~(PAGESIZE
- 1);
9732 mprotect((void *)start
, end
- start
,
9733 PROT_READ
| PROT_WRITE
| PROT_EXEC
);
9741 /* launch the compiled program with the given arguments */
9742 int tcc_run(TCCState
*s1
, int argc
, char **argv
)
9744 int (*prog_main
)(int, char **);
9746 if (tcc_relocate(s1
) < 0)
9749 prog_main
= tcc_get_symbol_err(s1
, "main");
9752 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
9753 error("debug mode currently not available for Windows");
9755 struct sigaction sigact
;
9756 /* install TCC signal handlers to print debug info on fatal
9758 sigact
.sa_flags
= SA_SIGINFO
| SA_RESETHAND
;
9759 sigact
.sa_sigaction
= sig_error
;
9760 sigemptyset(&sigact
.sa_mask
);
9761 sigaction(SIGFPE
, &sigact
, NULL
);
9762 sigaction(SIGILL
, &sigact
, NULL
);
9763 sigaction(SIGSEGV
, &sigact
, NULL
);
9764 sigaction(SIGBUS
, &sigact
, NULL
);
9765 sigaction(SIGABRT
, &sigact
, NULL
);
9769 #ifdef CONFIG_TCC_BCHECK
9770 if (do_bounds_check
) {
9771 void (*bound_init
)(void);
9773 /* set error function */
9774 rt_bound_error_msg
= (void *)tcc_get_symbol_err(s1
,
9775 "__bound_error_msg");
9777 /* XXX: use .init section so that it also work in binary ? */
9778 bound_init
= (void *)tcc_get_symbol_err(s1
, "__bound_init");
9782 return (*prog_main
)(argc
, argv
);
9785 TCCState
*tcc_new(void)
9792 s
= tcc_mallocz(sizeof(TCCState
));
9796 s
->output_type
= TCC_OUTPUT_MEMORY
;
9798 /* init isid table */
9800 isidnum_table
[i
] = isid(i
) || isnum(i
);
9802 /* add all tokens */
9804 memset(hash_ident
, 0, TOK_HASH_SIZE
* sizeof(TokenSym
*));
9806 tok_ident
= TOK_IDENT
;
9815 ts
= tok_alloc(p
, r
- p
- 1);
9819 /* we add dummy defines for some special macros to speed up tests
9820 and to have working defined() */
9821 define_push(TOK___LINE__
, MACRO_OBJ
, NULL
, NULL
);
9822 define_push(TOK___FILE__
, MACRO_OBJ
, NULL
, NULL
);
9823 define_push(TOK___DATE__
, MACRO_OBJ
, NULL
, NULL
);
9824 define_push(TOK___TIME__
, MACRO_OBJ
, NULL
, NULL
);
9826 /* standard defines */
9827 tcc_define_symbol(s
, "__STDC__", NULL
);
9828 #if defined(TCC_TARGET_I386)
9829 tcc_define_symbol(s
, "__i386__", NULL
);
9831 #if defined(TCC_TARGET_ARM)
9832 tcc_define_symbol(s
, "__ARM_ARCH_4__", NULL
);
9833 tcc_define_symbol(s
, "__arm_elf__", NULL
);
9834 tcc_define_symbol(s
, "__arm_elf", NULL
);
9835 tcc_define_symbol(s
, "arm_elf", NULL
);
9836 tcc_define_symbol(s
, "__arm__", NULL
);
9837 tcc_define_symbol(s
, "__arm", NULL
);
9838 tcc_define_symbol(s
, "arm", NULL
);
9839 tcc_define_symbol(s
, "__APCS_32__", NULL
);
9842 tcc_define_symbol(s
, "__linux__", NULL
);
9843 tcc_define_symbol(s
, "linux", NULL
);
9845 /* tiny C specific defines */
9846 tcc_define_symbol(s
, "__TINYC__", NULL
);
9848 /* tiny C & gcc defines */
9849 tcc_define_symbol(s
, "__SIZE_TYPE__", "unsigned int");
9850 tcc_define_symbol(s
, "__PTRDIFF_TYPE__", "int");
9851 #ifdef TCC_TARGET_PE
9852 tcc_define_symbol(s
, "__WCHAR_TYPE__", "unsigned short");
9854 tcc_define_symbol(s
, "__WCHAR_TYPE__", "int");
9857 /* default library paths */
9858 #ifdef TCC_TARGET_PE
9861 snprintf(buf
, sizeof(buf
), "%s/lib", tcc_lib_path
);
9862 tcc_add_library_path(s
, buf
);
9865 tcc_add_library_path(s
, "/usr/local/lib");
9866 tcc_add_library_path(s
, "/usr/lib");
9867 tcc_add_library_path(s
, "/lib");
9870 /* no section zero */
9871 dynarray_add((void ***)&s
->sections
, &s
->nb_sections
, NULL
);
9873 /* create standard sections */
9874 text_section
= new_section(s
, ".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
9875 data_section
= new_section(s
, ".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
9876 bss_section
= new_section(s
, ".bss", SHT_NOBITS
, SHF_ALLOC
| SHF_WRITE
);
9878 /* symbols are always generated for linking stage */
9879 symtab_section
= new_symtab(s
, ".symtab", SHT_SYMTAB
, 0,
9881 ".hashtab", SHF_PRIVATE
);
9882 strtab_section
= symtab_section
->link
;
9884 /* private symbol table for dynamic symbols */
9885 s
->dynsymtab_section
= new_symtab(s
, ".dynsymtab", SHT_SYMTAB
, SHF_PRIVATE
,
9887 ".dynhashtab", SHF_PRIVATE
);
9888 s
->alacarte_link
= 1;
9890 #ifdef CHAR_IS_UNSIGNED
9891 s
->char_is_unsigned
= 1;
9893 #if defined(TCC_TARGET_PE) && 0
9894 /* XXX: currently the PE linker is not ready to support that */
9895 s
->leading_underscore
= 1;
9900 void tcc_delete(TCCState
*s1
)
9904 /* free -D defines */
9908 n
= tok_ident
- TOK_IDENT
;
9909 for(i
= 0; i
< n
; i
++)
9910 tcc_free(table_ident
[i
]);
9911 tcc_free(table_ident
);
9913 /* free all sections */
9915 free_section(symtab_section
->hash
);
9917 free_section(s1
->dynsymtab_section
->hash
);
9918 free_section(s1
->dynsymtab_section
->link
);
9919 free_section(s1
->dynsymtab_section
);
9921 for(i
= 1; i
< s1
->nb_sections
; i
++)
9922 free_section(s1
->sections
[i
]);
9923 tcc_free(s1
->sections
);
9925 /* free loaded dlls array */
9926 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++)
9927 tcc_free(s1
->loaded_dlls
[i
]);
9928 tcc_free(s1
->loaded_dlls
);
9931 for(i
= 0; i
< s1
->nb_library_paths
; i
++)
9932 tcc_free(s1
->library_paths
[i
]);
9933 tcc_free(s1
->library_paths
);
9935 /* cached includes */
9936 for(i
= 0; i
< s1
->nb_cached_includes
; i
++)
9937 tcc_free(s1
->cached_includes
[i
]);
9938 tcc_free(s1
->cached_includes
);
9940 for(i
= 0; i
< s1
->nb_include_paths
; i
++)
9941 tcc_free(s1
->include_paths
[i
]);
9942 tcc_free(s1
->include_paths
);
9944 for(i
= 0; i
< s1
->nb_sysinclude_paths
; i
++)
9945 tcc_free(s1
->sysinclude_paths
[i
]);
9946 tcc_free(s1
->sysinclude_paths
);
9951 int tcc_add_include_path(TCCState
*s1
, const char *pathname
)
9955 pathname1
= tcc_strdup(pathname
);
9956 dynarray_add((void ***)&s1
->include_paths
, &s1
->nb_include_paths
, pathname1
);
9960 int tcc_add_sysinclude_path(TCCState
*s1
, const char *pathname
)
9964 pathname1
= tcc_strdup(pathname
);
9965 dynarray_add((void ***)&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
, pathname1
);
9969 static int tcc_add_file_internal(TCCState
*s1
, const char *filename
, int flags
)
9971 const char *ext
, *filename1
;
9974 BufferedFile
*saved_file
;
9976 /* find source file type with extension */
9977 filename1
= strrchr(filename
, '/');
9981 filename1
= filename
;
9982 ext
= strrchr(filename1
, '.');
9988 file
= tcc_open(s1
, filename
);
9990 if (flags
& AFF_PRINT_ERROR
) {
9991 error_noabort("file '%s' not found", filename
);
9997 if (flags
& AFF_PREPROCESS
) {
9998 ret
= tcc_preprocess(s1
);
9999 } else if (!ext
|| !strcmp(ext
, "c")) {
10000 /* C file assumed */
10001 ret
= tcc_compile(s1
);
10003 #ifdef CONFIG_TCC_ASM
10004 if (!strcmp(ext
, "S")) {
10005 /* preprocessed assembler */
10006 ret
= tcc_assemble(s1
, 1);
10007 } else if (!strcmp(ext
, "s")) {
10008 /* non preprocessed assembler */
10009 ret
= tcc_assemble(s1
, 0);
10012 #ifdef TCC_TARGET_PE
10013 if (!strcmp(ext
, "def")) {
10014 ret
= pe_load_def_file(s1
, fdopen(file
->fd
, "rb"));
10019 /* assume executable format: auto guess file type */
10020 ret
= read(fd
, &ehdr
, sizeof(ehdr
));
10021 lseek(fd
, 0, SEEK_SET
);
10023 error_noabort("could not read header");
10025 } else if (ret
!= sizeof(ehdr
)) {
10026 goto try_load_script
;
10029 if (ehdr
.e_ident
[0] == ELFMAG0
&&
10030 ehdr
.e_ident
[1] == ELFMAG1
&&
10031 ehdr
.e_ident
[2] == ELFMAG2
&&
10032 ehdr
.e_ident
[3] == ELFMAG3
) {
10033 file
->line_num
= 0; /* do not display line number if error */
10034 if (ehdr
.e_type
== ET_REL
) {
10035 ret
= tcc_load_object_file(s1
, fd
, 0);
10036 } else if (ehdr
.e_type
== ET_DYN
) {
10037 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
10038 #ifdef TCC_TARGET_PE
10042 h
= dlopen(filename
, RTLD_GLOBAL
| RTLD_LAZY
);
10049 ret
= tcc_load_dll(s1
, fd
, filename
,
10050 (flags
& AFF_REFERENCED_DLL
) != 0);
10053 error_noabort("unrecognized ELF file");
10056 } else if (memcmp((char *)&ehdr
, ARMAG
, 8) == 0) {
10057 file
->line_num
= 0; /* do not display line number if error */
10058 ret
= tcc_load_archive(s1
, fd
);
10060 #ifdef TCC_TARGET_COFF
10061 if (*(uint16_t *)(&ehdr
) == COFF_C67_MAGIC
) {
10062 ret
= tcc_load_coff(s1
, fd
);
10066 /* as GNU ld, consider it is an ld script if not recognized */
10068 ret
= tcc_load_ldscript(s1
);
10070 error_noabort("unrecognized file type");
10085 int tcc_add_file(TCCState
*s
, const char *filename
)
10087 return tcc_add_file_internal(s
, filename
, AFF_PRINT_ERROR
);
10090 int tcc_add_library_path(TCCState
*s
, const char *pathname
)
10094 pathname1
= tcc_strdup(pathname
);
10095 dynarray_add((void ***)&s
->library_paths
, &s
->nb_library_paths
, pathname1
);
10099 /* find and load a dll. Return non zero if not found */
10100 /* XXX: add '-rpath' option support ? */
10101 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
)
10106 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
10107 snprintf(buf
, sizeof(buf
), "%s/%s",
10108 s
->library_paths
[i
], filename
);
10109 if (tcc_add_file_internal(s
, buf
, flags
) == 0)
10115 /* the library name is the same as the argument of the '-l' option */
10116 int tcc_add_library(TCCState
*s
, const char *libraryname
)
10121 /* first we look for the dynamic library if not static linking */
10122 if (!s
->static_link
) {
10123 #ifdef TCC_TARGET_PE
10124 snprintf(buf
, sizeof(buf
), "%s.def", libraryname
);
10126 snprintf(buf
, sizeof(buf
), "lib%s.so", libraryname
);
10128 if (tcc_add_dll(s
, buf
, 0) == 0)
10132 /* then we look for the static library */
10133 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
10134 snprintf(buf
, sizeof(buf
), "%s/lib%s.a",
10135 s
->library_paths
[i
], libraryname
);
10136 if (tcc_add_file_internal(s
, buf
, 0) == 0)
10142 int tcc_add_symbol(TCCState
*s
, const char *name
, unsigned long val
)
10144 add_elf_sym(symtab_section
, val
, 0,
10145 ELF32_ST_INFO(STB_GLOBAL
, STT_NOTYPE
), 0,
10150 int tcc_set_output_type(TCCState
*s
, int output_type
)
10152 s
->output_type
= output_type
;
10154 if (!s
->nostdinc
) {
10157 /* default include paths */
10158 /* XXX: reverse order needed if -isystem support */
10159 #ifndef TCC_TARGET_PE
10160 tcc_add_sysinclude_path(s
, "/usr/local/include");
10161 tcc_add_sysinclude_path(s
, "/usr/include");
10163 snprintf(buf
, sizeof(buf
), "%s/include", tcc_lib_path
);
10164 tcc_add_sysinclude_path(s
, buf
);
10165 #ifdef TCC_TARGET_PE
10166 snprintf(buf
, sizeof(buf
), "%s/include/winapi", tcc_lib_path
);
10167 tcc_add_sysinclude_path(s
, buf
);
10171 /* if bound checking, then add corresponding sections */
10172 #ifdef CONFIG_TCC_BCHECK
10173 if (do_bounds_check
) {
10174 /* define symbol */
10175 tcc_define_symbol(s
, "__BOUNDS_CHECKING_ON", NULL
);
10176 /* create bounds sections */
10177 bounds_section
= new_section(s
, ".bounds",
10178 SHT_PROGBITS
, SHF_ALLOC
);
10179 lbounds_section
= new_section(s
, ".lbounds",
10180 SHT_PROGBITS
, SHF_ALLOC
);
10184 if (s
->char_is_unsigned
) {
10185 tcc_define_symbol(s
, "__CHAR_UNSIGNED__", NULL
);
10188 /* add debug sections */
10191 stab_section
= new_section(s
, ".stab", SHT_PROGBITS
, 0);
10192 stab_section
->sh_entsize
= sizeof(Stab_Sym
);
10193 stabstr_section
= new_section(s
, ".stabstr", SHT_STRTAB
, 0);
10194 put_elf_str(stabstr_section
, "");
10195 stab_section
->link
= stabstr_section
;
10196 /* put first entry */
10197 put_stabs("", 0, 0, 0, 0);
10200 /* add libc crt1/crti objects */
10201 #ifndef TCC_TARGET_PE
10202 if ((output_type
== TCC_OUTPUT_EXE
|| output_type
== TCC_OUTPUT_DLL
) &&
10204 if (output_type
!= TCC_OUTPUT_DLL
)
10205 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crt1.o");
10206 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crti.o");
10212 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10213 #define FD_INVERT 0x0002 /* invert value before storing */
10215 typedef struct FlagDef
{
10221 static const FlagDef warning_defs
[] = {
10222 { offsetof(TCCState
, warn_unsupported
), 0, "unsupported" },
10223 { offsetof(TCCState
, warn_write_strings
), 0, "write-strings" },
10224 { offsetof(TCCState
, warn_error
), 0, "error" },
10225 { offsetof(TCCState
, warn_implicit_function_declaration
), WD_ALL
,
10226 "implicit-function-declaration" },
10229 static int set_flag(TCCState
*s
, const FlagDef
*flags
, int nb_flags
,
10230 const char *name
, int value
)
10237 if (r
[0] == 'n' && r
[1] == 'o' && r
[2] == '-') {
10241 for(i
= 0, p
= flags
; i
< nb_flags
; i
++, p
++) {
10242 if (!strcmp(r
, p
->name
))
10247 if (p
->flags
& FD_INVERT
)
10249 *(int *)((uint8_t *)s
+ p
->offset
) = value
;
10254 /* set/reset a warning */
10255 int tcc_set_warning(TCCState
*s
, const char *warning_name
, int value
)
10260 if (!strcmp(warning_name
, "all")) {
10261 for(i
= 0, p
= warning_defs
; i
< countof(warning_defs
); i
++, p
++) {
10262 if (p
->flags
& WD_ALL
)
10263 *(int *)((uint8_t *)s
+ p
->offset
) = 1;
10267 return set_flag(s
, warning_defs
, countof(warning_defs
),
10268 warning_name
, value
);
10272 static const FlagDef flag_defs
[] = {
10273 { offsetof(TCCState
, char_is_unsigned
), 0, "unsigned-char" },
10274 { offsetof(TCCState
, char_is_unsigned
), FD_INVERT
, "signed-char" },
10275 { offsetof(TCCState
, nocommon
), FD_INVERT
, "common" },
10276 { offsetof(TCCState
, leading_underscore
), 0, "leading-underscore" },
10279 /* set/reset a flag */
10280 int tcc_set_flag(TCCState
*s
, const char *flag_name
, int value
)
10282 return set_flag(s
, flag_defs
, countof(flag_defs
),
10286 #if !defined(LIBTCC)
10288 /* extract the basename of a file */
10289 static const char *tcc_basename(const char *name
)
10292 p
= strrchr(name
, '/');
10295 p
= strrchr(name
, '\\');
10304 static int64_t getclock_us(void)
10309 return (tb
.time
* 1000LL + tb
.millitm
) * 1000LL;
10312 gettimeofday(&tv
, NULL
);
10313 return tv
.tv_sec
* 1000000LL + tv
.tv_usec
;
10319 printf("tcc version " TCC_VERSION
" - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10320 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10321 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10322 " [infile1 infile2...] [-run infile args...]\n"
10324 "General options:\n"
10325 " -v display current version\n"
10326 " -c compile only - generate an object file\n"
10327 " -o outfile set output filename\n"
10328 " -Bdir set tcc internal library path\n"
10329 " -bench output compilation statistics\n"
10330 " -run run compiled source\n"
10331 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10332 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10333 " -w disable all warnings\n"
10334 "Preprocessor options:\n"
10335 " -E preprocess only\n"
10336 " -Idir add include path 'dir'\n"
10337 " -Dsym[=val] define 'sym' with value 'val'\n"
10338 " -Usym undefine 'sym'\n"
10339 "Linker options:\n"
10340 " -Ldir add library path 'dir'\n"
10341 " -llib link with dynamic or static library 'lib'\n"
10342 " -shared generate a shared library\n"
10343 " -static static linking\n"
10344 " -rdynamic export all global symbols to dynamic linker\n"
10345 " -r relocatable output\n"
10346 "Debugger options:\n"
10347 " -g generate runtime debug info\n"
10348 #ifdef CONFIG_TCC_BCHECK
10349 " -b compile with built-in memory and bounds checker (implies -g)\n"
10351 " -bt N show N callers in stack traces\n"
10355 #define TCC_OPTION_HAS_ARG 0x0001
10356 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10358 typedef struct TCCOption
{
10386 TCC_OPTION_nostdinc
,
10387 TCC_OPTION_nostdlib
,
10388 TCC_OPTION_print_search_dirs
,
10389 TCC_OPTION_rdynamic
,
10397 static const TCCOption tcc_options
[] = {
10398 { "h", TCC_OPTION_HELP
, 0 },
10399 { "?", TCC_OPTION_HELP
, 0 },
10400 { "I", TCC_OPTION_I
, TCC_OPTION_HAS_ARG
},
10401 { "D", TCC_OPTION_D
, TCC_OPTION_HAS_ARG
},
10402 { "U", TCC_OPTION_U
, TCC_OPTION_HAS_ARG
},
10403 { "L", TCC_OPTION_L
, TCC_OPTION_HAS_ARG
},
10404 { "B", TCC_OPTION_B
, TCC_OPTION_HAS_ARG
},
10405 { "l", TCC_OPTION_l
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10406 { "bench", TCC_OPTION_bench
, 0 },
10407 { "bt", TCC_OPTION_bt
, TCC_OPTION_HAS_ARG
},
10408 #ifdef CONFIG_TCC_BCHECK
10409 { "b", TCC_OPTION_b
, 0 },
10411 { "g", TCC_OPTION_g
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10412 { "c", TCC_OPTION_c
, 0 },
10413 { "static", TCC_OPTION_static
, 0 },
10414 { "shared", TCC_OPTION_shared
, 0 },
10415 { "o", TCC_OPTION_o
, TCC_OPTION_HAS_ARG
},
10416 { "run", TCC_OPTION_run
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10417 { "rdynamic", TCC_OPTION_rdynamic
, 0 },
10418 { "r", TCC_OPTION_r
, 0 },
10419 { "Wl,", TCC_OPTION_Wl
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10420 { "W", TCC_OPTION_W
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10421 { "O", TCC_OPTION_O
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10422 { "m", TCC_OPTION_m
, TCC_OPTION_HAS_ARG
},
10423 { "f", TCC_OPTION_f
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10424 { "nostdinc", TCC_OPTION_nostdinc
, 0 },
10425 { "nostdlib", TCC_OPTION_nostdlib
, 0 },
10426 { "print-search-dirs", TCC_OPTION_print_search_dirs
, 0 },
10427 { "v", TCC_OPTION_v
, 0 },
10428 { "w", TCC_OPTION_w
, 0 },
10429 { "pipe", TCC_OPTION_pipe
, 0},
10430 { "E", TCC_OPTION_E
, 0},
10434 /* convert 'str' into an array of space separated strings */
10435 static int expand_args(char ***pargv
, const char *str
)
10444 while (is_space(*str
))
10449 while (*str
!= '\0' && !is_space(*str
))
10452 arg
= tcc_malloc(len
+ 1);
10453 memcpy(arg
, s1
, len
);
10455 dynarray_add((void ***)&argv
, &argc
, arg
);
10461 static char **files
;
10462 static int nb_files
, nb_libraries
;
10463 static int multiple_files
;
10464 static int print_search_dirs
;
10465 static int output_type
;
10466 static int reloc_output
;
10467 static const char *outfile
;
10469 int parse_args(TCCState
*s
, int argc
, char **argv
)
10472 const TCCOption
*popt
;
10473 const char *optarg
, *p1
, *r1
;
10478 if (optind
>= argc
) {
10479 if (nb_files
== 0 && !print_search_dirs
)
10484 r
= argv
[optind
++];
10486 /* add a new file */
10487 dynarray_add((void ***)&files
, &nb_files
, r
);
10488 if (!multiple_files
) {
10490 /* argv[0] will be this file */
10494 /* find option in table (match only the first chars */
10495 popt
= tcc_options
;
10499 error("invalid option -- '%s'", r
);
10512 if (popt
->flags
& TCC_OPTION_HAS_ARG
) {
10513 if (*r1
!= '\0' || (popt
->flags
& TCC_OPTION_NOSEP
)) {
10516 if (optind
>= argc
)
10517 error("argument to '%s' is missing", r
);
10518 optarg
= argv
[optind
++];
10526 switch(popt
->index
) {
10527 case TCC_OPTION_HELP
:
10532 if (tcc_add_include_path(s
, optarg
) < 0)
10533 error("too many include paths");
10538 sym
= (char *)optarg
;
10539 value
= strchr(sym
, '=');
10544 tcc_define_symbol(s
, sym
, value
);
10548 tcc_undefine_symbol(s
, optarg
);
10551 tcc_add_library_path(s
, optarg
);
10554 /* set tcc utilities path (mainly for tcc development) */
10555 tcc_lib_path
= optarg
;
10558 dynarray_add((void ***)&files
, &nb_files
, r
);
10561 case TCC_OPTION_bench
:
10564 case TCC_OPTION_bt
:
10565 num_callers
= atoi(optarg
);
10567 #ifdef CONFIG_TCC_BCHECK
10569 do_bounds_check
= 1;
10577 multiple_files
= 1;
10578 output_type
= TCC_OUTPUT_OBJ
;
10580 case TCC_OPTION_static
:
10581 s
->static_link
= 1;
10583 case TCC_OPTION_shared
:
10584 output_type
= TCC_OUTPUT_DLL
;
10587 multiple_files
= 1;
10591 /* generate a .o merging several output files */
10593 output_type
= TCC_OUTPUT_OBJ
;
10595 case TCC_OPTION_nostdinc
:
10598 case TCC_OPTION_nostdlib
:
10601 case TCC_OPTION_print_search_dirs
:
10602 print_search_dirs
= 1;
10604 case TCC_OPTION_run
:
10608 argc1
= expand_args(&argv1
, optarg
);
10610 parse_args(s
, argc1
, argv1
);
10612 multiple_files
= 0;
10613 output_type
= TCC_OUTPUT_MEMORY
;
10617 printf("tcc version %s\n", TCC_VERSION
);
10620 if (tcc_set_flag(s
, optarg
, 1) < 0 && s
->warn_unsupported
)
10621 goto unsupported_option
;
10624 if (tcc_set_warning(s
, optarg
, 1) < 0 &&
10625 s
->warn_unsupported
)
10626 goto unsupported_option
;
10631 case TCC_OPTION_rdynamic
:
10634 case TCC_OPTION_Wl
:
10637 if (strstart(optarg
, "-Ttext,", &p
)) {
10638 s
->text_addr
= strtoul(p
, NULL
, 16);
10639 s
->has_text_addr
= 1;
10640 } else if (strstart(optarg
, "--oformat,", &p
)) {
10641 if (strstart(p
, "elf32-", NULL
)) {
10642 s
->output_format
= TCC_OUTPUT_FORMAT_ELF
;
10643 } else if (!strcmp(p
, "binary")) {
10644 s
->output_format
= TCC_OUTPUT_FORMAT_BINARY
;
10646 #ifdef TCC_TARGET_COFF
10647 if (!strcmp(p
, "coff")) {
10648 s
->output_format
= TCC_OUTPUT_FORMAT_COFF
;
10652 error("target %s not found", p
);
10655 error("unsupported linker option '%s'", optarg
);
10660 output_type
= TCC_OUTPUT_PREPROCESS
;
10663 if (s
->warn_unsupported
) {
10664 unsupported_option
:
10665 warning("unsupported option '%s'", r
);
10674 int main(int argc
, char **argv
)
10678 int nb_objfiles
, ret
, optind
;
10679 char objfilename
[1024];
10680 int64_t start_time
= 0;
10683 /* on win32, we suppose the lib and includes are at the location
10686 static char path
[1024];
10689 GetModuleFileNameA(NULL
, path
, sizeof path
);
10690 p
= d
= strlwr(path
);
10693 if (*d
== '\\') *d
= '/', p
= d
;
10697 tcc_lib_path
= path
;
10702 output_type
= TCC_OUTPUT_EXE
;
10704 multiple_files
= 1;
10709 print_search_dirs
= 0;
10711 optind
= parse_args(s
, argc
- 1, argv
+ 1) + 1;
10713 if (print_search_dirs
) {
10714 /* enough for Linux kernel */
10715 printf("install: %s/\n", tcc_lib_path
);
10719 nb_objfiles
= nb_files
- nb_libraries
;
10721 /* if outfile provided without other options, we output an
10723 if (outfile
&& output_type
== TCC_OUTPUT_MEMORY
)
10724 output_type
= TCC_OUTPUT_EXE
;
10726 /* check -c consistency : only single file handled. XXX: checks file type */
10727 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
10728 /* accepts only a single input file */
10729 if (nb_objfiles
!= 1)
10730 error("cannot specify multiple files with -c");
10731 if (nb_libraries
!= 0)
10732 error("cannot specify libraries with -c");
10736 if (output_type
== TCC_OUTPUT_PREPROCESS
) {
10738 s
->outfile
= stdout
;
10740 s
->outfile
= fopen(outfile
, "wb");
10742 error("could not open '%s", outfile
);
10744 } else if (output_type
!= TCC_OUTPUT_MEMORY
) {
10746 /* compute default outfile name */
10747 pstrcpy(objfilename
, sizeof(objfilename
) - 1,
10749 tcc_basename(files
[0]));
10750 #ifdef TCC_TARGET_PE
10751 pe_guess_outfile(objfilename
, output_type
);
10753 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
10754 char *ext
= strrchr(objfilename
, '.');
10756 goto default_outfile
;
10757 /* add .o extension */
10758 strcpy(ext
+ 1, "o");
10761 pstrcpy(objfilename
, sizeof(objfilename
), "a.out");
10764 outfile
= objfilename
;
10769 start_time
= getclock_us();
10772 tcc_set_output_type(s
, output_type
);
10774 /* compile or add each files or library */
10775 for(i
= 0;i
< nb_files
; i
++) {
10776 const char *filename
;
10778 filename
= files
[i
];
10779 if (output_type
== TCC_OUTPUT_PREPROCESS
) {
10780 tcc_add_file_internal(s
, filename
,
10781 AFF_PRINT_ERROR
| AFF_PREPROCESS
);
10783 if (filename
[0] == '-') {
10784 if (tcc_add_library(s
, filename
+ 2) < 0)
10785 error("cannot find %s", filename
);
10787 if (tcc_add_file(s
, filename
) < 0) {
10795 /* free all files */
10800 total_time
= (double)(getclock_us() - start_time
) / 1000000.0;
10801 if (total_time
< 0.001)
10802 total_time
= 0.001;
10803 if (total_bytes
< 1)
10805 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10806 tok_ident
- TOK_IDENT
, total_lines
, total_bytes
,
10807 total_time
, (int)(total_lines
/ total_time
),
10808 total_bytes
/ total_time
/ 1000000.0);
10811 if (s
->output_type
== TCC_OUTPUT_PREPROCESS
) {
10813 fclose(s
->outfile
);
10815 } else if (s
->output_type
== TCC_OUTPUT_MEMORY
) {
10816 ret
= tcc_run(s
, argc
- optind
, argv
+ optind
);
10818 #ifdef TCC_TARGET_PE
10819 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
10820 ret
= tcc_output_pe(s
, outfile
);
10824 tcc_output_file(s
, outfile
);
10828 /* XXX: cannot do it with bound checking because of the malloc hooks */
10829 if (!do_bounds_check
)
10834 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size
, mem_max_size
);