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 int func_attr
; /* calling convention, exports, ... */
236 /* -------------------------------------------------- */
237 /* gr: wrappers for casting sym->r for other purposes */
245 #define FUNC_CALL(r) (((func_attr_t*)&(r))->func_call)
246 #define FUNC_EXPORT(r) (((func_attr_t*)&(r))->func_export)
247 #define FUNC_ARGS(r) (((func_attr_t*)&(r))->func_args)
248 #define INLINE_DEF(r) (*(int **)&(r))
249 /* -------------------------------------------------- */
251 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
252 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
253 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
255 /* stored in 'Sym.c' field */
256 #define FUNC_NEW 1 /* ansi function prototype */
257 #define FUNC_OLD 2 /* old function prototype */
258 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
260 /* stored in 'Sym.r' field */
261 #define FUNC_CDECL 0 /* standard c call */
262 #define FUNC_STDCALL 1 /* pascal c call */
263 #define FUNC_FASTCALL1 2 /* first param in %eax */
264 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
265 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
266 #define FUNC_FASTCALLW 5 /* first parameter in %ecx, %edx */
268 /* field 'Sym.t' for macros */
269 #define MACRO_OBJ 0 /* object like macro */
270 #define MACRO_FUNC 1 /* function like macro */
272 /* field 'Sym.r' for C labels */
273 #define LABEL_DEFINED 0 /* label is defined */
274 #define LABEL_FORWARD 1 /* label is forward defined */
275 #define LABEL_DECLARED 2 /* label is declared but never used */
277 /* type_decl() types */
278 #define TYPE_ABSTRACT 1 /* type without variable */
279 #define TYPE_DIRECT 2 /* type with variable */
281 #define IO_BUF_SIZE 8192
283 typedef struct BufferedFile
{
287 int line_num
; /* current line number - here to simplify code */
288 int ifndef_macro
; /* #ifndef macro / #endif search */
289 int ifndef_macro_saved
; /* saved ifndef_macro */
290 int *ifdef_stack_ptr
; /* ifdef_stack value at the start of the file */
291 char inc_type
; /* type of include */
292 char inc_filename
[512]; /* filename specified by the user */
293 char filename
[1024]; /* current filename - here to simplify code */
294 unsigned char buffer
[IO_BUF_SIZE
+ 1]; /* extra size for CH_EOB char */
297 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
298 #define CH_EOF (-1) /* end of file */
300 /* parsing state (used to save parser state to reparse part of the
301 source several times) */
302 typedef struct ParseState
{
309 /* used to record tokens */
310 typedef struct TokenString
{
317 /* include file cache, used to find files faster and also to eliminate
318 inclusion if the include file is protected by #ifndef ... #endif */
319 typedef struct CachedInclude
{
321 int hash_next
; /* -1 if none */
322 char type
; /* '"' or '>' to give include type */
323 char filename
[1]; /* path specified in #include */
326 #define CACHED_INCLUDES_HASH_SIZE 512
329 static struct BufferedFile
*file
;
332 static CString tokcstr
; /* current parsed string, if any */
333 /* additional informations about token */
334 static int tok_flags
;
335 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
336 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
337 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
338 #define TOK_FLAG_EOF 0x0008 /* end of file */
340 static int *macro_ptr
, *macro_ptr_allocated
;
341 static int *unget_saved_macro_ptr
;
342 static int unget_saved_buffer
[TOK_MAX_SIZE
+ 1];
343 static int unget_buffer_enabled
;
344 static int parse_flags
;
345 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
346 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
347 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
348 token. line feed is also
350 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
352 static Section
*text_section
, *data_section
, *bss_section
; /* predefined sections */
353 static Section
*cur_text_section
; /* current section where function code is
355 #ifdef CONFIG_TCC_ASM
356 static Section
*last_text_section
; /* to handle .previous asm directive */
358 /* bound check related sections */
359 static Section
*bounds_section
; /* contains global data bound description */
360 static Section
*lbounds_section
; /* contains local data bound description */
361 /* symbol sections */
362 static Section
*symtab_section
, *strtab_section
;
365 static Section
*stab_section
, *stabstr_section
;
367 /* loc : local variable index
368 ind : output code index
370 anon_sym: anonymous symbol index
372 static int rsym
, anon_sym
, ind
, loc
;
373 /* expression generation modifiers */
374 static int const_wanted
; /* true if constant wanted */
375 static int nocode_wanted
; /* true if no code generation wanted for an expression */
376 static int global_expr
; /* true if compound literals must be allocated
377 globally (used during initializers parsing */
378 static CType func_vt
; /* current function return type (used by return
381 static int last_line_num
, last_ind
, func_ind
; /* debug last line number and pc */
382 static int tok_ident
;
383 static TokenSym
**table_ident
;
384 static TokenSym
*hash_ident
[TOK_HASH_SIZE
];
385 static char token_buf
[STRING_MAX_SIZE
+ 1];
386 static char *funcname
;
387 static Sym
*global_stack
, *local_stack
;
388 static Sym
*define_stack
;
389 static Sym
*global_label_stack
, *local_label_stack
;
390 /* symbol allocator */
391 #define SYM_POOL_NB (8192 / sizeof(Sym))
392 static Sym
*sym_free_first
;
394 static SValue vstack
[VSTACK_SIZE
], *vtop
;
395 /* some predefined types */
396 static CType char_pointer_type
, func_old_type
, int_type
;
397 /* true if isid(c) || isnum(c) */
398 static unsigned char isidnum_table
[256];
400 /* display some information during compilation */
401 static int verbose
= 0;
403 /* compile with debug symbol (and use them if error during execution) */
404 static int do_debug
= 0;
406 /* compile with built-in memory and bounds checker */
407 static int do_bounds_check
= 0;
409 /* display benchmark infos */
411 static int do_bench
= 0;
413 static int total_lines
;
414 static int total_bytes
;
416 /* use GNU C extensions */
417 static int gnu_ext
= 1;
419 /* use Tiny C extensions */
420 static int tcc_ext
= 1;
422 /* max number of callers shown if error */
423 static int num_callers
= 6;
424 static const char **rt_bound_error_msg
;
426 /* XXX: get rid of this ASAP */
427 static struct TCCState
*tcc_state
;
429 /* give the path of the tcc libraries */
430 static const char *tcc_lib_path
= CONFIG_TCCDIR
;
435 BufferedFile
**include_stack_ptr
;
436 int *ifdef_stack_ptr
;
438 /* include file handling */
439 char **include_paths
;
440 int nb_include_paths
;
441 char **sysinclude_paths
;
442 int nb_sysinclude_paths
;
443 CachedInclude
**cached_includes
;
444 int nb_cached_includes
;
446 char **library_paths
;
447 int nb_library_paths
;
449 /* array of all loaded dlls (including those referenced by loaded
451 DLLReference
**loaded_dlls
;
456 int nb_sections
; /* number of sections, including first dummy section */
461 unsigned long *got_offsets
;
463 /* give the correspondance from symtab indexes to dynsym indexes */
464 int *symtab_to_dynsym
;
466 /* temporary dynamic symbol sections (for dll loading) */
467 Section
*dynsymtab_section
;
468 /* exported dynamic symbol section */
471 int nostdinc
; /* if true, no standard headers are added */
472 int nostdlib
; /* if true, no standard libraries are added */
474 int nocommon
; /* if true, do not use common symbols for .bss data */
476 /* if true, static linking is performed */
479 /* soname as specified on the command line (-soname) */
482 /* if true, all symbols are exported */
485 /* if true, only link in referenced objects from archive */
488 /* address of text section */
489 unsigned long text_addr
;
492 /* output format, see TCC_OUTPUT_FORMAT_xxx */
495 /* C language options */
496 int char_is_unsigned
;
497 int leading_underscore
;
499 /* warning switches */
500 int warn_write_strings
;
501 int warn_unsupported
;
504 int warn_implicit_function_declaration
;
508 void (*error_func
)(void *opaque
, const char *msg
);
509 int error_set_jmp_enabled
;
510 jmp_buf error_jmp_buf
;
513 /* tiny assembler state */
516 /* see include_stack_ptr */
517 BufferedFile
*include_stack
[INCLUDE_STACK_SIZE
];
519 /* see ifdef_stack_ptr */
520 int ifdef_stack
[IFDEF_STACK_SIZE
];
522 /* see cached_includes */
523 int cached_includes_hash
[CACHED_INCLUDES_HASH_SIZE
];
526 int pack_stack
[PACK_STACK_SIZE
];
529 /* output file for preprocessing */
533 /* The current value can be: */
534 #define VT_VALMASK 0x00ff
535 #define VT_CONST 0x00f0 /* constant in vc
536 (must be first non register value) */
537 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
538 #define VT_LOCAL 0x00f2 /* offset on stack */
539 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
540 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
541 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
542 #define VT_LVAL 0x0100 /* var is an lvalue */
543 #define VT_SYM 0x0200 /* a symbol value is added */
544 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
545 char/short stored in integer registers) */
546 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
547 dereferencing value */
548 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
549 bounding function call point is in vc */
550 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
551 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
552 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
553 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
556 #define VT_INT 0 /* integer type */
557 #define VT_BYTE 1 /* signed byte type */
558 #define VT_SHORT 2 /* short type */
559 #define VT_VOID 3 /* void type */
560 #define VT_PTR 4 /* pointer */
561 #define VT_ENUM 5 /* enum definition */
562 #define VT_FUNC 6 /* function type */
563 #define VT_STRUCT 7 /* struct/union definition */
564 #define VT_FLOAT 8 /* IEEE float */
565 #define VT_DOUBLE 9 /* IEEE double */
566 #define VT_LDOUBLE 10 /* IEEE long double */
567 #define VT_BOOL 11 /* ISOC99 boolean type */
568 #define VT_LLONG 12 /* 64 bit integer */
569 #define VT_LONG 13 /* long integer (NEVER USED as type, only
571 #define VT_BTYPE 0x000f /* mask for basic type */
572 #define VT_UNSIGNED 0x0010 /* unsigned type */
573 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
574 #define VT_BITFIELD 0x0040 /* bitfield modifier */
575 #define VT_CONSTANT 0x0800 /* const modifier */
576 #define VT_VOLATILE 0x1000 /* volatile modifier */
577 #define VT_SIGNED 0x2000 /* signed type */
580 #define VT_EXTERN 0x00000080 /* extern definition */
581 #define VT_STATIC 0x00000100 /* static variable */
582 #define VT_TYPEDEF 0x00000200 /* typedef definition */
583 #define VT_INLINE 0x00000400 /* inline definition */
585 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
587 /* type mask (except storage) */
588 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
589 #define VT_TYPE (~(VT_STORAGE))
593 /* warning: the following compare tokens depend on i386 asm code */
600 #define TOK_Nset 0x98
601 #define TOK_Nclear 0x99
607 #define TOK_LAND 0xa0
611 #define TOK_MID 0xa3 /* inc/dec, to void constant */
613 #define TOK_UDIV 0xb0 /* unsigned division */
614 #define TOK_UMOD 0xb1 /* unsigned modulo */
615 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
616 #define TOK_CINT 0xb3 /* number in tokc */
617 #define TOK_CCHAR 0xb4 /* char constant in tokc */
618 #define TOK_STR 0xb5 /* pointer to string in tokc */
619 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
620 #define TOK_LCHAR 0xb7
621 #define TOK_LSTR 0xb8
622 #define TOK_CFLOAT 0xb9 /* float constant */
623 #define TOK_LINENUM 0xba /* line number info */
624 #define TOK_CDOUBLE 0xc0 /* double constant */
625 #define TOK_CLDOUBLE 0xc1 /* long double constant */
626 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
627 #define TOK_ADDC1 0xc3 /* add with carry generation */
628 #define TOK_ADDC2 0xc4 /* add with carry use */
629 #define TOK_SUBC1 0xc5 /* add with carry generation */
630 #define TOK_SUBC2 0xc6 /* add with carry use */
631 #define TOK_CUINT 0xc8 /* unsigned int constant */
632 #define TOK_CLLONG 0xc9 /* long long constant */
633 #define TOK_CULLONG 0xca /* unsigned long long constant */
634 #define TOK_ARROW 0xcb
635 #define TOK_DOTS 0xcc /* three dots */
636 #define TOK_SHR 0xcd /* unsigned shift right */
637 #define TOK_PPNUM 0xce /* preprocessor number */
639 #define TOK_SHL 0x01 /* shift left */
640 #define TOK_SAR 0x02 /* signed shift right */
642 /* assignement operators : normal operator or 0x80 */
643 #define TOK_A_MOD 0xa5
644 #define TOK_A_AND 0xa6
645 #define TOK_A_MUL 0xaa
646 #define TOK_A_ADD 0xab
647 #define TOK_A_SUB 0xad
648 #define TOK_A_DIV 0xaf
649 #define TOK_A_XOR 0xde
650 #define TOK_A_OR 0xfc
651 #define TOK_A_SHL 0x81
652 #define TOK_A_SAR 0x82
655 #define offsetof(type, field) ((size_t) &((type *)0)->field)
659 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
662 /* WARNING: the content of this string encodes token numbers */
663 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";
665 #define TOK_EOF (-1) /* end of file */
666 #define TOK_LINEFEED 10 /* line feed */
668 /* all identificators and strings have token above that */
669 #define TOK_IDENT 256
671 /* only used for i386 asm opcodes definitions */
672 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
675 DEF(TOK_ASM_ ## x ## b, #x "b") \
676 DEF(TOK_ASM_ ## x ## w, #x "w") \
677 DEF(TOK_ASM_ ## x ## l, #x "l") \
678 DEF(TOK_ASM_ ## x, #x)
681 DEF(TOK_ASM_ ## x ## w, #x "w") \
682 DEF(TOK_ASM_ ## x ## l, #x "l") \
683 DEF(TOK_ASM_ ## x, #x)
686 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
687 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
688 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
689 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
692 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
693 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
696 #define DEF_ASMTEST(x) \
728 #define TOK_ASM_int TOK_INT
731 TOK_LAST
= TOK_IDENT
- 1,
732 #define DEF(id, str) id,
737 static const char tcc_keywords
[] =
738 #define DEF(id, str) str "\0"
743 #define TOK_UIDENT TOK_DEFINE
746 #define snprintf _snprintf
747 #define vsnprintf _vsnprintf
749 #define strtold (long double)strtod
750 #define strtof (float)strtod
751 #define strtoll (long long)strtol
753 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__) || defined(__DragonFly__) \
754 || defined(__OpenBSD__)
755 /* currently incorrect */
756 long double strtold(const char *nptr
, char **endptr
)
758 return (long double)strtod(nptr
, endptr
);
760 float strtof(const char *nptr
, char **endptr
)
762 return (float)strtod(nptr
, endptr
);
765 /* XXX: need to define this to use them in non ISOC99 context */
766 extern float strtof (const char *__nptr
, char **__endptr
);
767 extern long double strtold (const char *__nptr
, char **__endptr
);
770 static char *pstrcpy(char *buf
, int buf_size
, const char *s
);
771 static char *pstrcat(char *buf
, int buf_size
, const char *s
);
772 static char *tcc_basename(const char *name
);
773 static char *tcc_fileextension (const char *p
);
775 static void next(void);
776 static void next_nomacro(void);
777 static void parse_expr_type(CType
*type
);
778 static void expr_type(CType
*type
);
779 static void unary_type(CType
*type
);
780 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
781 int case_reg
, int is_expr
);
782 static int expr_const(void);
783 static void expr_eq(void);
784 static void gexpr(void);
785 static void gen_inline_functions(void);
786 static void decl(int l
);
787 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
788 int first
, int size_only
);
789 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
790 int has_init
, int v
, int scope
);
792 void gv2(int rc1
, int rc2
);
793 void move_reg(int r
, int s
);
794 void save_regs(int n
);
795 void save_reg(int r
);
800 int get_reg_ex(int rc
,int rc2
);
803 struct macro_level
*prev
;
807 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
808 const int *macro_str
, struct macro_level
**can_read_stream
);
810 void force_charshort_cast(int t
);
811 static void gen_cast(CType
*type
);
813 static Sym
*sym_find(int v
);
814 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
);
817 static int type_size(CType
*type
, int *a
);
818 static inline CType
*pointed_type(CType
*type
);
819 static int pointed_size(CType
*type
);
820 static int lvalue_type(int t
);
821 static int parse_btype(CType
*type
, AttributeDef
*ad
);
822 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
);
823 static int compare_types(CType
*type1
, CType
*type2
, int unqualified
);
824 static int is_compatible_types(CType
*type1
, CType
*type2
);
825 static int is_compatible_parameter_types(CType
*type1
, CType
*type2
);
827 int ieee_finite(double d
);
828 void error(const char *fmt
, ...);
832 void lexpand_nr(void);
833 static void vpush_global_sym(CType
*type
, int v
);
834 void vset(CType
*type
, int r
, int v
);
835 void type_to_str(char *buf
, int buf_size
,
836 CType
*type
, const char *varstr
);
837 char *get_tok_str(int v
, CValue
*cv
);
838 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
839 unsigned long offset
, unsigned long size
);
840 static Sym
*external_global_sym(int v
, CType
*type
, int r
);
842 /* section generation */
843 static void section_realloc(Section
*sec
, unsigned long new_size
);
844 static void *section_ptr_add(Section
*sec
, unsigned long size
);
845 static void put_extern_sym(Sym
*sym
, Section
*section
,
846 unsigned long value
, unsigned long size
);
847 static void greloc(Section
*s
, Sym
*sym
, unsigned long addr
, int type
);
848 static int put_elf_str(Section
*s
, const char *sym
);
849 static int put_elf_sym(Section
*s
,
850 unsigned long value
, unsigned long size
,
851 int info
, int other
, int shndx
, const char *name
);
852 static int add_elf_sym(Section
*s
, unsigned long value
, unsigned long size
,
853 int info
, int other
, int sh_num
, const char *name
);
854 static void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
855 int type
, int symbol
);
856 static void put_stabs(const char *str
, int type
, int other
, int desc
,
857 unsigned long value
);
858 static void put_stabs_r(const char *str
, int type
, int other
, int desc
,
859 unsigned long value
, Section
*sec
, int sym_index
);
860 static void put_stabn(int type
, int other
, int desc
, int value
);
861 static void put_stabd(int type
, int other
, int desc
);
862 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
);
864 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
865 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
866 #define AFF_PREPROCESS 0x0004 /* preprocess file */
867 static int tcc_add_file_internal(TCCState
*s
, const char *filename
, int flags
);
870 int tcc_output_coff(TCCState
*s1
, FILE *f
);
873 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
);
874 int pe_load_def_file(struct TCCState
*s1
, int fd
);
875 int pe_test_res_file(void *v
, int size
);
876 int pe_load_res_file(struct TCCState
*s1
, int fd
);
877 void pe_add_runtime(struct TCCState
*s1
);
878 void pe_guess_outfile(char *objfilename
, int output_type
);
879 int pe_output_file(struct TCCState
*s1
, const char *filename
);
883 #ifdef CONFIG_TCC_ASM
885 typedef struct ExprValue
{
890 #define MAX_ASM_OPERANDS 30
892 typedef struct ASMOperand
{
893 int id
; /* GCC 3 optionnal identifier (0 if number only supported */
895 char asm_str
[16]; /* computed asm string for operand */
896 SValue
*vt
; /* C value of the expression */
897 int ref_index
; /* if >= 0, gives reference to a output constraint */
898 int input_index
; /* if >= 0, gives reference to an input constraint */
899 int priority
; /* priority, used to assign registers */
900 int reg
; /* if >= 0, register number used for this operand */
901 int is_llong
; /* true if double register value */
902 int is_memory
; /* true if memory operand */
903 int is_rw
; /* for '+' modifier */
906 static void asm_expr(TCCState
*s1
, ExprValue
*pe
);
907 static int asm_int_expr(TCCState
*s1
);
908 static int find_constraint(ASMOperand
*operands
, int nb_operands
,
909 const char *name
, const char **pp
);
911 static int tcc_assemble(TCCState
*s1
, int do_preprocess
);
915 static void asm_instr(void);
916 static void asm_global_instr(void);
918 /* true if float/double/long double type */
919 static inline int is_float(int t
)
923 return bt
== VT_LDOUBLE
|| bt
== VT_DOUBLE
|| bt
== VT_FLOAT
;
926 #ifdef TCC_TARGET_I386
927 #include "i386-gen.c"
930 #ifdef TCC_TARGET_ARM
934 #ifdef TCC_TARGET_C67
938 #ifdef CONFIG_TCC_STATIC
940 #define RTLD_LAZY 0x001
941 #define RTLD_NOW 0x002
942 #define RTLD_GLOBAL 0x100
943 #define RTLD_DEFAULT NULL
945 /* dummy function for profiling */
946 void *dlopen(const char *filename
, int flag
)
951 const char *dlerror(void)
956 typedef struct TCCSyms
{
961 #define TCCSYM(a) { #a, &a, },
963 /* add the symbol you want here if no dynamic linking is done */
964 static TCCSyms tcc_syms
[] = {
965 #if !defined(CONFIG_TCCBOOT)
974 void *resolve_sym(TCCState
*s1
, const char *symbol
, int type
)
978 while (p
->str
!= NULL
) {
979 if (!strcmp(p
->str
, symbol
))
986 #elif !defined(_WIN32)
990 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
)
992 return dlsym(RTLD_DEFAULT
, sym
);
997 /********************************************************/
999 /* we use our own 'finite' function to avoid potential problems with
1000 non standard math libs */
1001 /* XXX: endianness dependent */
1002 int ieee_finite(double d
)
1005 return ((unsigned)((p
[1] | 0x800fffff) + 1)) >> 31;
1008 /* copy a string and truncate it. */
1009 static char *pstrcpy(char *buf
, int buf_size
, const char *s
)
1016 q_end
= buf
+ buf_size
- 1;
1028 /* strcat and truncate. */
1029 static char *pstrcat(char *buf
, int buf_size
, const char *s
)
1034 pstrcpy(buf
+ len
, buf_size
- len
, s
);
1038 static int strstart(const char *str
, const char *val
, const char **ptr
)
1043 while (*q
!= '\0') {
1054 /* extract the basename of a file */
1055 static char *tcc_basename(const char *name
)
1057 char *p
= strchr(name
, 0);
1068 static char *tcc_fileextension (const char *name
)
1070 char *b
= tcc_basename(name
);
1071 char *e
= strrchr(b
, '.');
1072 return e
? e
: strchr(b
, 0);
1076 char *normalize_slashes(char *path
)
1079 for (p
= path
; *p
; ++p
)
1085 char *w32_tcc_lib_path(void)
1087 /* on win32, we suppose the lib and includes are at the location
1089 char path
[1024], *p
;
1090 GetModuleFileNameA(NULL
, path
, sizeof path
);
1091 p
= tcc_basename(normalize_slashes(strlwr(path
)));
1092 if (p
- 5 > path
&& 0 == strncmp(p
- 5, "/bin/", 5))
1097 return strdup(path
);
1101 void set_pages_executable(void *ptr
, unsigned long length
)
1104 unsigned long old_protect
;
1105 VirtualProtect(ptr
, length
, PAGE_EXECUTE_READWRITE
, &old_protect
);
1107 unsigned long start
, end
;
1108 start
= (unsigned long)ptr
& ~(PAGESIZE
- 1);
1109 end
= (unsigned long)ptr
+ length
;
1110 end
= (end
+ PAGESIZE
- 1) & ~(PAGESIZE
- 1);
1111 mprotect((void *)start
, end
- start
, PROT_READ
| PROT_WRITE
| PROT_EXEC
);
1115 /* memory management */
1121 static inline void tcc_free(void *ptr
)
1124 mem_cur_size
-= malloc_usable_size(ptr
);
1129 static void *tcc_malloc(unsigned long size
)
1134 error("memory full");
1136 mem_cur_size
+= malloc_usable_size(ptr
);
1137 if (mem_cur_size
> mem_max_size
)
1138 mem_max_size
= mem_cur_size
;
1143 static void *tcc_mallocz(unsigned long size
)
1146 ptr
= tcc_malloc(size
);
1147 memset(ptr
, 0, size
);
1151 static inline void *tcc_realloc(void *ptr
, unsigned long size
)
1155 mem_cur_size
-= malloc_usable_size(ptr
);
1157 ptr1
= realloc(ptr
, size
);
1159 /* NOTE: count not correct if alloc error, but not critical */
1160 mem_cur_size
+= malloc_usable_size(ptr1
);
1161 if (mem_cur_size
> mem_max_size
)
1162 mem_max_size
= mem_cur_size
;
1167 static char *tcc_strdup(const char *str
)
1170 ptr
= tcc_malloc(strlen(str
) + 1);
1175 #define free(p) use_tcc_free(p)
1176 #define malloc(s) use_tcc_malloc(s)
1177 #define realloc(p, s) use_tcc_realloc(p, s)
1179 static void dynarray_add(void ***ptab
, int *nb_ptr
, void *data
)
1186 /* every power of two we double array size */
1187 if ((nb
& (nb
- 1)) == 0) {
1192 pp
= tcc_realloc(pp
, nb_alloc
* sizeof(void *));
1194 error("memory full");
1201 static void dynarray_reset(void *pp
, int *n
)
1204 for (p
= *(void***)pp
; *n
; ++p
, --*n
)
1207 tcc_free(*(void**)pp
);
1211 /* symbol allocator */
1212 static Sym
*__sym_malloc(void)
1214 Sym
*sym_pool
, *sym
, *last_sym
;
1217 sym_pool
= tcc_malloc(SYM_POOL_NB
* sizeof(Sym
));
1219 last_sym
= sym_free_first
;
1221 for(i
= 0; i
< SYM_POOL_NB
; i
++) {
1222 sym
->next
= last_sym
;
1226 sym_free_first
= last_sym
;
1230 static inline Sym
*sym_malloc(void)
1233 sym
= sym_free_first
;
1235 sym
= __sym_malloc();
1236 sym_free_first
= sym
->next
;
1240 static inline void sym_free(Sym
*sym
)
1242 sym
->next
= sym_free_first
;
1243 sym_free_first
= sym
;
1246 Section
*new_section(TCCState
*s1
, const char *name
, int sh_type
, int sh_flags
)
1250 sec
= tcc_mallocz(sizeof(Section
) + strlen(name
));
1251 strcpy(sec
->name
, name
);
1252 sec
->sh_type
= sh_type
;
1253 sec
->sh_flags
= sh_flags
;
1260 sec
->sh_addralign
= 4;
1263 sec
->sh_addralign
= 1;
1266 sec
->sh_addralign
= 32; /* default conservative alignment */
1270 /* only add section if not private */
1271 if (!(sh_flags
& SHF_PRIVATE
)) {
1272 sec
->sh_num
= s1
->nb_sections
;
1273 dynarray_add((void ***)&s1
->sections
, &s1
->nb_sections
, sec
);
1278 static void free_section(Section
*s
)
1284 /* realloc section and set its content to zero */
1285 static void section_realloc(Section
*sec
, unsigned long new_size
)
1288 unsigned char *data
;
1290 size
= sec
->data_allocated
;
1293 while (size
< new_size
)
1295 data
= tcc_realloc(sec
->data
, size
);
1297 error("memory full");
1298 memset(data
+ sec
->data_allocated
, 0, size
- sec
->data_allocated
);
1300 sec
->data_allocated
= size
;
1303 /* reserve at least 'size' bytes in section 'sec' from
1304 sec->data_offset. */
1305 static void *section_ptr_add(Section
*sec
, unsigned long size
)
1307 unsigned long offset
, offset1
;
1309 offset
= sec
->data_offset
;
1310 offset1
= offset
+ size
;
1311 if (offset1
> sec
->data_allocated
)
1312 section_realloc(sec
, offset1
);
1313 sec
->data_offset
= offset1
;
1314 return sec
->data
+ offset
;
1317 /* return a reference to a section, and create it if it does not
1319 Section
*find_section(TCCState
*s1
, const char *name
)
1323 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1324 sec
= s1
->sections
[i
];
1325 if (!strcmp(name
, sec
->name
))
1328 /* sections are created as PROGBITS */
1329 return new_section(s1
, name
, SHT_PROGBITS
, SHF_ALLOC
);
1332 #define SECTION_ABS ((void *)1)
1334 /* update sym->c so that it points to an external symbol in section
1335 'section' with value 'value' */
1336 static void put_extern_sym2(Sym
*sym
, Section
*section
,
1337 unsigned long value
, unsigned long size
,
1338 int can_add_underscore
)
1340 int sym_type
, sym_bind
, sh_num
, info
, other
, attr
;
1345 if (section
== NULL
)
1347 else if (section
== SECTION_ABS
)
1350 sh_num
= section
->sh_num
;
1354 if ((sym
->type
.t
& VT_BTYPE
) == VT_FUNC
) {
1355 sym_type
= STT_FUNC
;
1356 #ifdef TCC_TARGET_PE
1358 attr
= sym
->type
.ref
->r
;
1359 if (FUNC_EXPORT(attr
))
1361 if (FUNC_CALL(attr
) == FUNC_STDCALL
)
1365 sym_type
= STT_OBJECT
;
1368 if (sym
->type
.t
& VT_STATIC
)
1369 sym_bind
= STB_LOCAL
;
1371 sym_bind
= STB_GLOBAL
;
1374 name
= get_tok_str(sym
->v
, NULL
);
1375 #ifdef CONFIG_TCC_BCHECK
1376 if (do_bounds_check
) {
1379 /* XXX: avoid doing that for statics ? */
1380 /* if bound checking is activated, we change some function
1381 names by adding the "__bound" prefix */
1384 /* XXX: we rely only on malloc hooks */
1397 strcpy(buf
, "__bound_");
1405 #ifdef TCC_TARGET_PE
1406 if ((other
& 2) && can_add_underscore
) {
1407 sprintf(buf1
, "_%s@%d", name
, FUNC_ARGS(attr
));
1411 if (tcc_state
->leading_underscore
&& can_add_underscore
) {
1413 pstrcpy(buf1
+ 1, sizeof(buf1
) - 1, name
);
1416 info
= ELF32_ST_INFO(sym_bind
, sym_type
);
1417 sym
->c
= add_elf_sym(symtab_section
, value
, size
, info
, other
, sh_num
, name
);
1419 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
1420 esym
->st_value
= value
;
1421 esym
->st_size
= size
;
1422 esym
->st_shndx
= sh_num
;
1423 esym
->st_other
|= other
;
1427 static void put_extern_sym(Sym
*sym
, Section
*section
,
1428 unsigned long value
, unsigned long size
)
1430 put_extern_sym2(sym
, section
, value
, size
, 1);
1433 /* add a new relocation entry to symbol 'sym' in section 's' */
1434 static void greloc(Section
*s
, Sym
*sym
, unsigned long offset
, int type
)
1437 put_extern_sym(sym
, NULL
, 0, 0);
1438 /* now we can add ELF relocation info */
1439 put_elf_reloc(symtab_section
, s
, offset
, type
, sym
->c
);
1442 static inline int isid(int c
)
1444 return (c
>= 'a' && c
<= 'z') ||
1445 (c
>= 'A' && c
<= 'Z') ||
1449 static inline int isnum(int c
)
1451 return c
>= '0' && c
<= '9';
1454 static inline int isoct(int c
)
1456 return c
>= '0' && c
<= '7';
1459 static inline int toup(int c
)
1461 if (c
>= 'a' && c
<= 'z')
1462 return c
- 'a' + 'A';
1467 static void strcat_vprintf(char *buf
, int buf_size
, const char *fmt
, va_list ap
)
1471 vsnprintf(buf
+ len
, buf_size
- len
, fmt
, ap
);
1474 static void strcat_printf(char *buf
, int buf_size
, const char *fmt
, ...)
1478 strcat_vprintf(buf
, buf_size
, fmt
, ap
);
1482 void error1(TCCState
*s1
, int is_warning
, const char *fmt
, va_list ap
)
1489 for(f
= s1
->include_stack
; f
< s1
->include_stack_ptr
; f
++)
1490 strcat_printf(buf
, sizeof(buf
), "In file included from %s:%d:\n",
1491 (*f
)->filename
, (*f
)->line_num
);
1492 if (file
->line_num
> 0) {
1493 strcat_printf(buf
, sizeof(buf
),
1494 "%s:%d: ", file
->filename
, file
->line_num
);
1496 strcat_printf(buf
, sizeof(buf
),
1497 "%s: ", file
->filename
);
1500 strcat_printf(buf
, sizeof(buf
),
1504 strcat_printf(buf
, sizeof(buf
), "warning: ");
1505 strcat_vprintf(buf
, sizeof(buf
), fmt
, ap
);
1507 if (!s1
->error_func
) {
1508 /* default case: stderr */
1509 fprintf(stderr
, "%s\n", buf
);
1511 s1
->error_func(s1
->error_opaque
, buf
);
1513 if (!is_warning
|| s1
->warn_error
)
1518 void tcc_set_error_func(TCCState
*s
, void *error_opaque
,
1519 void (*error_func
)(void *opaque
, const char *msg
))
1521 s
->error_opaque
= error_opaque
;
1522 s
->error_func
= error_func
;
1526 /* error without aborting current compilation */
1527 void error_noabort(const char *fmt
, ...)
1529 TCCState
*s1
= tcc_state
;
1533 error1(s1
, 0, fmt
, ap
);
1537 void error(const char *fmt
, ...)
1539 TCCState
*s1
= tcc_state
;
1543 error1(s1
, 0, fmt
, ap
);
1545 /* better than nothing: in some cases, we accept to handle errors */
1546 if (s1
->error_set_jmp_enabled
) {
1547 longjmp(s1
->error_jmp_buf
, 1);
1549 /* XXX: eliminate this someday */
1554 void expect(const char *msg
)
1556 error("%s expected", msg
);
1559 void warning(const char *fmt
, ...)
1561 TCCState
*s1
= tcc_state
;
1568 error1(s1
, 1, fmt
, ap
);
1575 error("'%c' expected", c
);
1579 static void test_lvalue(void)
1581 if (!(vtop
->r
& VT_LVAL
))
1585 /* allocate a new token */
1586 static TokenSym
*tok_alloc_new(TokenSym
**pts
, const char *str
, int len
)
1588 TokenSym
*ts
, **ptable
;
1591 if (tok_ident
>= SYM_FIRST_ANOM
)
1592 error("memory full");
1594 /* expand token table if needed */
1595 i
= tok_ident
- TOK_IDENT
;
1596 if ((i
% TOK_ALLOC_INCR
) == 0) {
1597 ptable
= tcc_realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
1599 error("memory full");
1600 table_ident
= ptable
;
1603 ts
= tcc_malloc(sizeof(TokenSym
) + len
);
1604 table_ident
[i
] = ts
;
1605 ts
->tok
= tok_ident
++;
1606 ts
->sym_define
= NULL
;
1607 ts
->sym_label
= NULL
;
1608 ts
->sym_struct
= NULL
;
1609 ts
->sym_identifier
= NULL
;
1611 ts
->hash_next
= NULL
;
1612 memcpy(ts
->str
, str
, len
);
1613 ts
->str
[len
] = '\0';
1618 #define TOK_HASH_INIT 1
1619 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1621 /* find a token and add it if not found */
1622 static TokenSym
*tok_alloc(const char *str
, int len
)
1624 TokenSym
*ts
, **pts
;
1630 h
= TOK_HASH_FUNC(h
, ((unsigned char *)str
)[i
]);
1631 h
&= (TOK_HASH_SIZE
- 1);
1633 pts
= &hash_ident
[h
];
1638 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
1640 pts
= &(ts
->hash_next
);
1642 return tok_alloc_new(pts
, str
, len
);
1645 /* CString handling */
1647 static void cstr_realloc(CString
*cstr
, int new_size
)
1652 size
= cstr
->size_allocated
;
1654 size
= 8; /* no need to allocate a too small first string */
1655 while (size
< new_size
)
1657 data
= tcc_realloc(cstr
->data_allocated
, size
);
1659 error("memory full");
1660 cstr
->data_allocated
= data
;
1661 cstr
->size_allocated
= size
;
1666 static inline void cstr_ccat(CString
*cstr
, int ch
)
1669 size
= cstr
->size
+ 1;
1670 if (size
> cstr
->size_allocated
)
1671 cstr_realloc(cstr
, size
);
1672 ((unsigned char *)cstr
->data
)[size
- 1] = ch
;
1676 static void cstr_cat(CString
*cstr
, const char *str
)
1688 /* add a wide char */
1689 static void cstr_wccat(CString
*cstr
, int ch
)
1692 size
= cstr
->size
+ sizeof(nwchar_t
);
1693 if (size
> cstr
->size_allocated
)
1694 cstr_realloc(cstr
, size
);
1695 *(nwchar_t
*)(((unsigned char *)cstr
->data
) + size
- sizeof(nwchar_t
)) = ch
;
1699 static void cstr_new(CString
*cstr
)
1701 memset(cstr
, 0, sizeof(CString
));
1704 /* free string and reset it to NULL */
1705 static void cstr_free(CString
*cstr
)
1707 tcc_free(cstr
->data_allocated
);
1711 #define cstr_reset(cstr) cstr_free(cstr)
1713 /* XXX: unicode ? */
1714 static void add_char(CString
*cstr
, int c
)
1716 if (c
== '\'' || c
== '\"' || c
== '\\') {
1717 /* XXX: could be more precise if char or string */
1718 cstr_ccat(cstr
, '\\');
1720 if (c
>= 32 && c
<= 126) {
1723 cstr_ccat(cstr
, '\\');
1725 cstr_ccat(cstr
, 'n');
1727 cstr_ccat(cstr
, '0' + ((c
>> 6) & 7));
1728 cstr_ccat(cstr
, '0' + ((c
>> 3) & 7));
1729 cstr_ccat(cstr
, '0' + (c
& 7));
1734 /* XXX: buffer overflow */
1735 /* XXX: float tokens */
1736 char *get_tok_str(int v
, CValue
*cv
)
1738 static char buf
[STRING_MAX_SIZE
+ 1];
1739 static CString cstr_buf
;
1745 /* NOTE: to go faster, we give a fixed buffer for small strings */
1746 cstr_reset(&cstr_buf
);
1747 cstr_buf
.data
= buf
;
1748 cstr_buf
.size_allocated
= sizeof(buf
);
1754 /* XXX: not quite exact, but only useful for testing */
1755 sprintf(p
, "%u", cv
->ui
);
1759 /* XXX: not quite exact, but only useful for testing */
1760 sprintf(p
, "%Lu", cv
->ull
);
1764 cstr_ccat(&cstr_buf
, '\'');
1765 add_char(&cstr_buf
, cv
->i
);
1766 cstr_ccat(&cstr_buf
, '\'');
1767 cstr_ccat(&cstr_buf
, '\0');
1771 len
= cstr
->size
- 1;
1773 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1774 cstr_ccat(&cstr_buf
, '\0');
1779 cstr_ccat(&cstr_buf
, '\"');
1781 len
= cstr
->size
- 1;
1783 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1785 len
= (cstr
->size
/ sizeof(nwchar_t
)) - 1;
1787 add_char(&cstr_buf
, ((nwchar_t
*)cstr
->data
)[i
]);
1789 cstr_ccat(&cstr_buf
, '\"');
1790 cstr_ccat(&cstr_buf
, '\0');
1799 return strcpy(p
, "...");
1801 return strcpy(p
, "<<=");
1803 return strcpy(p
, ">>=");
1805 if (v
< TOK_IDENT
) {
1806 /* search in two bytes table */
1820 } else if (v
< tok_ident
) {
1821 return table_ident
[v
- TOK_IDENT
]->str
;
1822 } else if (v
>= SYM_FIRST_ANOM
) {
1823 /* special name for anonymous symbol */
1824 sprintf(p
, "L.%u", v
- SYM_FIRST_ANOM
);
1826 /* should never happen */
1831 return cstr_buf
.data
;
1834 /* push, without hashing */
1835 static Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
1849 /* find a symbol and return its associated structure. 's' is the top
1850 of the symbol stack */
1851 static Sym
*sym_find2(Sym
*s
, int v
)
1861 /* structure lookup */
1862 static inline Sym
*struct_find(int v
)
1865 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1867 return table_ident
[v
]->sym_struct
;
1870 /* find an identifier */
1871 static inline Sym
*sym_find(int v
)
1874 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1876 return table_ident
[v
]->sym_identifier
;
1879 /* push a given symbol on the symbol stack */
1880 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
)
1889 s
= sym_push2(ps
, v
, type
->t
, c
);
1890 s
->type
.ref
= type
->ref
;
1892 /* don't record fields or anonymous symbols */
1894 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1895 /* record symbol in token array */
1896 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1898 ps
= &ts
->sym_struct
;
1900 ps
= &ts
->sym_identifier
;
1907 /* push a global identifier */
1908 static Sym
*global_identifier_push(int v
, int t
, int c
)
1911 s
= sym_push2(&global_stack
, v
, t
, c
);
1912 /* don't record anonymous symbol */
1913 if (v
< SYM_FIRST_ANOM
) {
1914 ps
= &table_ident
[v
- TOK_IDENT
]->sym_identifier
;
1915 /* modify the top most local identifier, so that
1916 sym_identifier will point to 's' when popped */
1918 ps
= &(*ps
)->prev_tok
;
1925 /* pop symbols until top reaches 'b' */
1926 static void sym_pop(Sym
**ptop
, Sym
*b
)
1936 /* remove symbol in token array */
1938 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1939 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1941 ps
= &ts
->sym_struct
;
1943 ps
= &ts
->sym_identifier
;
1954 BufferedFile
*tcc_open(TCCState
*s1
, const char *filename
)
1959 fd
= open(filename
, O_RDONLY
| O_BINARY
);
1962 bf
= tcc_malloc(sizeof(BufferedFile
));
1968 bf
->buf_ptr
= bf
->buffer
;
1969 bf
->buf_end
= bf
->buffer
;
1970 bf
->buffer
[0] = CH_EOB
; /* put eob symbol */
1971 pstrcpy(bf
->filename
, sizeof(bf
->filename
), filename
);
1973 normalize_slashes(bf
->filename
);
1976 bf
->ifndef_macro
= 0;
1977 bf
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
1978 // printf("opening '%s'\n", filename);
1982 void tcc_close(BufferedFile
*bf
)
1984 total_lines
+= bf
->line_num
;
1989 /* fill input buffer and peek next char */
1990 static int tcc_peekc_slow(BufferedFile
*bf
)
1993 /* only tries to read if really end of buffer */
1994 if (bf
->buf_ptr
>= bf
->buf_end
) {
1996 #if defined(PARSE_DEBUG)
2001 len
= read(bf
->fd
, bf
->buffer
, len
);
2008 bf
->buf_ptr
= bf
->buffer
;
2009 bf
->buf_end
= bf
->buffer
+ len
;
2010 *bf
->buf_end
= CH_EOB
;
2012 if (bf
->buf_ptr
< bf
->buf_end
) {
2013 return bf
->buf_ptr
[0];
2015 bf
->buf_ptr
= bf
->buf_end
;
2020 /* return the current character, handling end of block if necessary
2022 static int handle_eob(void)
2024 return tcc_peekc_slow(file
);
2027 /* read next char from current input file and handle end of input buffer */
2028 static inline void inp(void)
2030 ch
= *(++(file
->buf_ptr
));
2031 /* end of buffer/file handling */
2036 /* handle '\[\r]\n' */
2037 static int handle_stray_noerror(void)
2039 while (ch
== '\\') {
2044 } else if (ch
== '\r') {
2058 static void handle_stray(void)
2060 if (handle_stray_noerror())
2061 error("stray '\\' in program");
2064 /* skip the stray and handle the \\n case. Output an error if
2065 incorrect char after the stray */
2066 static int handle_stray1(uint8_t *p
)
2070 if (p
>= file
->buf_end
) {
2087 /* handle just the EOB case, but not stray */
2088 #define PEEKC_EOB(c, p)\
2099 /* handle the complicated stray case */
2100 #define PEEKC(c, p)\
2105 c = handle_stray1(p);\
2110 /* input with '\[\r]\n' handling. Note that this function cannot
2111 handle other characters after '\', so you cannot call it inside
2112 strings or comments */
2113 static void minp(void)
2121 /* single line C++ comments */
2122 static uint8_t *parse_line_comment(uint8_t *p
)
2130 if (c
== '\n' || c
== CH_EOF
) {
2132 } else if (c
== '\\') {
2141 } else if (c
== '\r') {
2159 static uint8_t *parse_comment(uint8_t *p
)
2165 /* fast skip loop */
2168 if (c
== '\n' || c
== '*' || c
== '\\')
2172 if (c
== '\n' || c
== '*' || c
== '\\')
2176 /* now we can handle all the cases */
2180 } else if (c
== '*') {
2186 } else if (c
== '/') {
2187 goto end_of_comment
;
2188 } else if (c
== '\\') {
2193 /* skip '\[\r]\n', otherwise just skip the stray */
2199 } else if (c
== '\r') {
2216 /* stray, eob or eof */
2221 error("unexpected end of file in comment");
2222 } else if (c
== '\\') {
2234 /* space exlcuding newline */
2235 static inline int is_space(int ch
)
2237 return ch
== ' ' || ch
== '\t' || ch
== '\v' || ch
== '\f' || ch
== '\r';
2240 static inline void skip_spaces(void)
2242 while (is_space(ch
))
2246 /* parse a string without interpreting escapes */
2247 static uint8_t *parse_pp_string(uint8_t *p
,
2248 int sep
, CString
*str
)
2256 } else if (c
== '\\') {
2261 unterminated_string
:
2262 /* XXX: indicate line number of start of string */
2263 error("missing terminating %c character", sep
);
2264 } else if (c
== '\\') {
2265 /* escape : just skip \[\r]\n */
2270 } else if (c
== '\r') {
2273 expect("'\n' after '\r'");
2276 } else if (c
== CH_EOF
) {
2277 goto unterminated_string
;
2280 cstr_ccat(str
, '\\');
2286 } else if (c
== '\n') {
2289 } else if (c
== '\r') {
2293 cstr_ccat(str
, '\r');
2309 /* skip block of text until #else, #elif or #endif. skip also pairs of
2311 void preprocess_skip(void)
2313 int a
, start_of_line
, c
, in_warn_or_error
;
2320 in_warn_or_error
= 0;
2341 } else if (c
== '\\') {
2342 ch
= file
->buf_ptr
[0];
2343 handle_stray_noerror();
2350 if (in_warn_or_error
)
2352 p
= parse_pp_string(p
, c
, NULL
);
2356 if (in_warn_or_error
)
2363 p
= parse_comment(p
);
2364 } else if (ch
== '/') {
2365 p
= parse_line_comment(p
);
2370 if (start_of_line
) {
2375 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
2377 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
2379 else if (tok
== TOK_ENDIF
)
2381 else if( tok
== TOK_ERROR
|| tok
== TOK_WARNING
)
2382 in_warn_or_error
= 1;
2396 /* ParseState handling */
2398 /* XXX: currently, no include file info is stored. Thus, we cannot display
2399 accurate messages if the function or data definition spans multiple
2402 /* save current parse state in 's' */
2403 void save_parse_state(ParseState
*s
)
2405 s
->line_num
= file
->line_num
;
2406 s
->macro_ptr
= macro_ptr
;
2411 /* restore parse state from 's' */
2412 void restore_parse_state(ParseState
*s
)
2414 file
->line_num
= s
->line_num
;
2415 macro_ptr
= s
->macro_ptr
;
2420 /* return the number of additional 'ints' necessary to store the
2422 static inline int tok_ext_size(int t
)
2436 error("unsupported token");
2443 return LDOUBLE_SIZE
/ 4;
2449 /* token string handling */
2451 static inline void tok_str_new(TokenString
*s
)
2455 s
->allocated_len
= 0;
2456 s
->last_line_num
= -1;
2459 static void tok_str_free(int *str
)
2464 static int *tok_str_realloc(TokenString
*s
)
2468 if (s
->allocated_len
== 0) {
2471 len
= s
->allocated_len
* 2;
2473 str
= tcc_realloc(s
->str
, len
* sizeof(int));
2475 error("memory full");
2476 s
->allocated_len
= len
;
2481 static void tok_str_add(TokenString
*s
, int t
)
2487 if (len
>= s
->allocated_len
)
2488 str
= tok_str_realloc(s
);
2493 static void tok_str_add2(TokenString
*s
, int t
, CValue
*cv
)
2500 /* allocate space for worst case */
2501 if (len
+ TOK_MAX_SIZE
> s
->allocated_len
)
2502 str
= tok_str_realloc(s
);
2511 str
[len
++] = cv
->tab
[0];
2520 nb_words
= (sizeof(CString
) + cv
->cstr
->size
+ 3) >> 2;
2521 while ((len
+ nb_words
) > s
->allocated_len
)
2522 str
= tok_str_realloc(s
);
2523 cstr
= (CString
*)(str
+ len
);
2525 cstr
->size
= cv
->cstr
->size
;
2526 cstr
->data_allocated
= NULL
;
2527 cstr
->size_allocated
= cstr
->size
;
2528 memcpy((char *)cstr
+ sizeof(CString
),
2529 cv
->cstr
->data
, cstr
->size
);
2536 #if LDOUBLE_SIZE == 8
2539 str
[len
++] = cv
->tab
[0];
2540 str
[len
++] = cv
->tab
[1];
2542 #if LDOUBLE_SIZE == 12
2544 str
[len
++] = cv
->tab
[0];
2545 str
[len
++] = cv
->tab
[1];
2546 str
[len
++] = cv
->tab
[2];
2547 #elif LDOUBLE_SIZE != 8
2548 #error add long double size support
2557 /* add the current parse token in token string 's' */
2558 static void tok_str_add_tok(TokenString
*s
)
2562 /* save line number info */
2563 if (file
->line_num
!= s
->last_line_num
) {
2564 s
->last_line_num
= file
->line_num
;
2565 cval
.i
= s
->last_line_num
;
2566 tok_str_add2(s
, TOK_LINENUM
, &cval
);
2568 tok_str_add2(s
, tok
, &tokc
);
2571 #if LDOUBLE_SIZE == 12
2572 #define LDOUBLE_GET(p, cv) \
2576 #elif LDOUBLE_SIZE == 8
2577 #define LDOUBLE_GET(p, cv) \
2581 #error add long double size support
2585 /* get a token from an integer array and increment pointer
2586 accordingly. we code it as a macro to avoid pointer aliasing. */
2587 #define TOK_GET(t, p, cv) \
2602 cv.cstr = (CString *)p; \
2603 cv.cstr->data = (char *)p + sizeof(CString);\
2604 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2613 case TOK_CLDOUBLE: \
2614 LDOUBLE_GET(p, cv); \
2615 p += LDOUBLE_SIZE / 4; \
2622 /* defines handling */
2623 static inline void define_push(int v
, int macro_type
, int *str
, Sym
*first_arg
)
2627 s
= sym_push2(&define_stack
, v
, macro_type
, (int)str
);
2628 s
->next
= first_arg
;
2629 table_ident
[v
- TOK_IDENT
]->sym_define
= s
;
2632 /* undefined a define symbol. Its name is just set to zero */
2633 static void define_undef(Sym
*s
)
2637 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2638 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2642 static inline Sym
*define_find(int v
)
2645 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2647 return table_ident
[v
]->sym_define
;
2650 /* free define stack until top reaches 'b' */
2651 static void free_defines(Sym
*b
)
2659 /* do not free args or predefined defines */
2661 tok_str_free((int *)top
->c
);
2663 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2664 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2672 static Sym
*label_find(int v
)
2675 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2677 return table_ident
[v
]->sym_label
;
2680 static Sym
*label_push(Sym
**ptop
, int v
, int flags
)
2683 s
= sym_push2(ptop
, v
, 0, 0);
2685 ps
= &table_ident
[v
- TOK_IDENT
]->sym_label
;
2686 if (ptop
== &global_label_stack
) {
2687 /* modify the top most local identifier, so that
2688 sym_identifier will point to 's' when popped */
2690 ps
= &(*ps
)->prev_tok
;
2697 /* pop labels until element last is reached. Look if any labels are
2698 undefined. Define symbols if '&&label' was used. */
2699 static void label_pop(Sym
**ptop
, Sym
*slast
)
2702 for(s
= *ptop
; s
!= slast
; s
= s1
) {
2704 if (s
->r
== LABEL_DECLARED
) {
2705 warning("label '%s' declared but not used", get_tok_str(s
->v
, NULL
));
2706 } else if (s
->r
== LABEL_FORWARD
) {
2707 error("label '%s' used but not defined",
2708 get_tok_str(s
->v
, NULL
));
2711 /* define corresponding symbol. A size of
2713 put_extern_sym(s
, cur_text_section
, (long)s
->next
, 1);
2717 table_ident
[s
->v
- TOK_IDENT
]->sym_label
= s
->prev_tok
;
2723 /* eval an expression for #if/#elif */
2724 static int expr_preprocess(void)
2730 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2731 next(); /* do macro subst */
2732 if (tok
== TOK_DEFINED
) {
2737 c
= define_find(tok
) != 0;
2742 } else if (tok
>= TOK_IDENT
) {
2743 /* if undefined macro */
2747 tok_str_add_tok(&str
);
2749 tok_str_add(&str
, -1); /* simulate end of file */
2750 tok_str_add(&str
, 0);
2751 /* now evaluate C constant expression */
2752 macro_ptr
= str
.str
;
2756 tok_str_free(str
.str
);
2760 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2761 static void tok_print(int *str
)
2767 TOK_GET(t
, str
, cval
);
2770 printf(" %s", get_tok_str(t
, &cval
));
2776 /* parse after #define */
2777 static void parse_define(void)
2779 Sym
*s
, *first
, **ps
;
2780 int v
, t
, varg
, is_vaargs
, c
;
2785 error("invalid macro name '%s'", get_tok_str(tok
, &tokc
));
2786 /* XXX: should check if same macro (ANSI) */
2789 /* '(' must be just after macro definition for MACRO_FUNC */
2790 c
= file
->buf_ptr
[0];
2792 c
= handle_stray1(file
->buf_ptr
);
2797 while (tok
!= ')') {
2801 if (varg
== TOK_DOTS
) {
2802 varg
= TOK___VA_ARGS__
;
2804 } else if (tok
== TOK_DOTS
&& gnu_ext
) {
2808 if (varg
< TOK_IDENT
)
2809 error("badly punctuated parameter list");
2810 s
= sym_push2(&define_stack
, varg
| SYM_FIELD
, is_vaargs
, 0);
2821 /* EOF testing necessary for '-D' handling */
2822 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2823 tok_str_add2(&str
, tok
, &tokc
);
2826 tok_str_add(&str
, 0);
2828 printf("define %s %d: ", get_tok_str(v
, NULL
), t
);
2831 define_push(v
, t
, str
.str
, first
);
2834 static inline int hash_cached_include(int type
, const char *filename
)
2836 const unsigned char *s
;
2840 h
= TOK_HASH_FUNC(h
, type
);
2843 h
= TOK_HASH_FUNC(h
, *s
);
2846 h
&= (CACHED_INCLUDES_HASH_SIZE
- 1);
2850 /* XXX: use a token or a hash table to accelerate matching ? */
2851 static CachedInclude
*search_cached_include(TCCState
*s1
,
2852 int type
, const char *filename
)
2856 h
= hash_cached_include(type
, filename
);
2857 i
= s1
->cached_includes_hash
[h
];
2861 e
= s1
->cached_includes
[i
- 1];
2862 if (e
->type
== type
&& !strcmp(e
->filename
, filename
))
2869 static inline void add_cached_include(TCCState
*s1
, int type
,
2870 const char *filename
, int ifndef_macro
)
2875 if (search_cached_include(s1
, type
, filename
))
2878 printf("adding cached '%s' %s\n", filename
, get_tok_str(ifndef_macro
, NULL
));
2880 e
= tcc_malloc(sizeof(CachedInclude
) + strlen(filename
));
2884 strcpy(e
->filename
, filename
);
2885 e
->ifndef_macro
= ifndef_macro
;
2886 dynarray_add((void ***)&s1
->cached_includes
, &s1
->nb_cached_includes
, e
);
2887 /* add in hash table */
2888 h
= hash_cached_include(type
, filename
);
2889 e
->hash_next
= s1
->cached_includes_hash
[h
];
2890 s1
->cached_includes_hash
[h
] = s1
->nb_cached_includes
;
2893 static void pragma_parse(TCCState
*s1
)
2898 if (tok
== TOK_pack
) {
2901 #pragma pack(1) // set
2902 #pragma pack() // reset to default
2903 #pragma pack(push,1) // push & set
2904 #pragma pack(pop) // restore previous
2908 if (tok
== TOK_ASM_pop
) {
2910 if (s1
->pack_stack_ptr
<= s1
->pack_stack
) {
2912 error("out of pack stack");
2914 s1
->pack_stack_ptr
--;
2918 if (tok
== TOK_ASM_push
) {
2920 if (s1
->pack_stack_ptr
>= s1
->pack_stack
+ PACK_STACK_SIZE
- 1)
2922 s1
->pack_stack_ptr
++;
2925 if (tok
!= TOK_CINT
) {
2927 error("invalid pack pragma");
2930 if (val
< 1 || val
> 16 || (val
& (val
- 1)) != 0)
2934 *s1
->pack_stack_ptr
= val
;
2940 /* is_bof is true if first non space token at beginning of file */
2941 static void preprocess(int is_bof
)
2943 TCCState
*s1
= tcc_state
;
2944 int size
, i
, c
, n
, saved_parse_flags
;
2951 saved_parse_flags
= parse_flags
;
2952 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
|
2953 PARSE_FLAG_LINEFEED
;
2963 s
= define_find(tok
);
2964 /* undefine symbol by putting an invalid name */
2969 case TOK_INCLUDE_NEXT
:
2970 ch
= file
->buf_ptr
[0];
2971 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2976 } else if (ch
== '\"') {
2981 while (ch
!= c
&& ch
!= '\n' && ch
!= CH_EOF
) {
2982 if ((q
- buf
) < sizeof(buf
) - 1)
2985 if (handle_stray_noerror() == 0)
2993 /* eat all spaces and comments after include */
2994 /* XXX: slightly incorrect */
2995 while (ch1
!= '\n' && ch1
!= CH_EOF
)
2999 /* computed #include : either we have only strings or
3000 we have anything enclosed in '<>' */
3003 if (tok
== TOK_STR
) {
3004 while (tok
!= TOK_LINEFEED
) {
3005 if (tok
!= TOK_STR
) {
3007 error("'#include' expects \"FILENAME\" or <FILENAME>");
3009 pstrcat(buf
, sizeof(buf
), (char *)tokc
.cstr
->data
);
3015 while (tok
!= TOK_LINEFEED
) {
3016 pstrcat(buf
, sizeof(buf
), get_tok_str(tok
, &tokc
));
3020 /* check syntax and remove '<>' */
3021 if (len
< 2 || buf
[0] != '<' || buf
[len
- 1] != '>')
3022 goto include_syntax
;
3023 memmove(buf
, buf
+ 1, len
- 2);
3024 buf
[len
- 2] = '\0';
3029 e
= search_cached_include(s1
, c
, buf
);
3030 if (e
&& define_find(e
->ifndef_macro
)) {
3031 /* no need to parse the include because the 'ifndef macro'
3034 printf("%s: skipping %s\n", file
->filename
, buf
);
3038 /* first search in current dir if "header.h" */
3039 size
= tcc_basename(file
->filename
) - file
->filename
;
3040 if (size
> sizeof(buf1
) - 1)
3041 size
= sizeof(buf1
) - 1;
3042 memcpy(buf1
, file
->filename
, size
);
3044 pstrcat(buf1
, sizeof(buf1
), buf
);
3045 f
= tcc_open(s1
, buf1
);
3047 if (tok
== TOK_INCLUDE_NEXT
)
3053 if (s1
->include_stack_ptr
>= s1
->include_stack
+ INCLUDE_STACK_SIZE
)
3054 error("#include recursion too deep");
3055 /* now search in all the include paths */
3056 n
= s1
->nb_include_paths
+ s1
->nb_sysinclude_paths
;
3057 for(i
= 0; i
< n
; i
++) {
3059 if (i
< s1
->nb_include_paths
)
3060 path
= s1
->include_paths
[i
];
3062 path
= s1
->sysinclude_paths
[i
- s1
->nb_include_paths
];
3063 pstrcpy(buf1
, sizeof(buf1
), path
);
3064 pstrcat(buf1
, sizeof(buf1
), "/");
3065 pstrcat(buf1
, sizeof(buf1
), buf
);
3066 f
= tcc_open(s1
, buf1
);
3068 if (tok
== TOK_INCLUDE_NEXT
)
3074 error("include file '%s' not found", buf
);
3078 printf("%s: including %s\n", file
->filename
, buf1
);
3081 pstrcpy(f
->inc_filename
, sizeof(f
->inc_filename
), buf
);
3082 /* push current file in stack */
3083 /* XXX: fix current line init */
3084 *s1
->include_stack_ptr
++ = file
;
3086 /* add include file debug info */
3088 put_stabs(file
->filename
, N_BINCL
, 0, 0, 0);
3090 tok_flags
|= TOK_FLAG_BOF
| TOK_FLAG_BOL
;
3091 ch
= file
->buf_ptr
[0];
3099 c
= expr_preprocess();
3105 if (tok
< TOK_IDENT
)
3106 error("invalid argument for '#if%sdef'", c
? "n" : "");
3110 printf("#ifndef %s\n", get_tok_str(tok
, NULL
));
3112 file
->ifndef_macro
= tok
;
3115 c
= (define_find(tok
) != 0) ^ c
;
3117 if (s1
->ifdef_stack_ptr
>= s1
->ifdef_stack
+ IFDEF_STACK_SIZE
)
3118 error("memory full");
3119 *s1
->ifdef_stack_ptr
++ = c
;
3122 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
3123 error("#else without matching #if");
3124 if (s1
->ifdef_stack_ptr
[-1] & 2)
3125 error("#else after #else");
3126 c
= (s1
->ifdef_stack_ptr
[-1] ^= 3);
3129 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
3130 error("#elif without matching #if");
3131 c
= s1
->ifdef_stack_ptr
[-1];
3133 error("#elif after #else");
3134 /* last #if/#elif expression was true: we skip */
3137 c
= expr_preprocess();
3138 s1
->ifdef_stack_ptr
[-1] = c
;
3148 if (s1
->ifdef_stack_ptr
<= file
->ifdef_stack_ptr
)
3149 error("#endif without matching #if");
3150 s1
->ifdef_stack_ptr
--;
3151 /* '#ifndef macro' was at the start of file. Now we check if
3152 an '#endif' is exactly at the end of file */
3153 if (file
->ifndef_macro
&&
3154 s1
->ifdef_stack_ptr
== file
->ifdef_stack_ptr
) {
3155 file
->ifndef_macro_saved
= file
->ifndef_macro
;
3156 /* need to set to zero to avoid false matches if another
3157 #ifndef at middle of file */
3158 file
->ifndef_macro
= 0;
3159 while (tok
!= TOK_LINEFEED
)
3161 tok_flags
|= TOK_FLAG_ENDIF
;
3167 if (tok
!= TOK_CINT
)
3169 file
->line_num
= tokc
.i
- 1; /* the line number will be incremented after */
3171 if (tok
!= TOK_LINEFEED
) {
3174 pstrcpy(file
->filename
, sizeof(file
->filename
),
3175 (char *)tokc
.cstr
->data
);
3181 ch
= file
->buf_ptr
[0];
3184 while (ch
!= '\n' && ch
!= CH_EOF
) {
3185 if ((q
- buf
) < sizeof(buf
) - 1)
3188 if (handle_stray_noerror() == 0)
3195 error("#error %s", buf
);
3197 warning("#warning %s", buf
);
3203 if (tok
== TOK_LINEFEED
|| tok
== '!' || tok
== TOK_CINT
) {
3204 /* '!' is ignored to allow C scripts. numbers are ignored
3205 to emulate cpp behaviour */
3207 if (!(saved_parse_flags
& PARSE_FLAG_ASM_COMMENTS
))
3208 warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok
, &tokc
));
3212 /* ignore other preprocess commands or #! for C scripts */
3213 while (tok
!= TOK_LINEFEED
)
3216 parse_flags
= saved_parse_flags
;
3219 /* evaluate escape codes in a string. */
3220 static void parse_escape_string(CString
*outstr
, const uint8_t *buf
, int is_long
)
3235 case '0': case '1': case '2': case '3':
3236 case '4': case '5': case '6': case '7':
3237 /* at most three octal digits */
3242 n
= n
* 8 + c
- '0';
3246 n
= n
* 8 + c
- '0';
3251 goto add_char_nonext
;
3259 if (c
>= 'a' && c
<= 'f')
3261 else if (c
>= 'A' && c
<= 'F')
3271 goto add_char_nonext
;
3295 goto invalid_escape
;
3305 if (c
>= '!' && c
<= '~')
3306 warning("unknown escape sequence: \'\\%c\'", c
);
3308 warning("unknown escape sequence: \'\\x%x\'", c
);
3315 cstr_ccat(outstr
, c
);
3317 cstr_wccat(outstr
, c
);
3319 /* add a trailing '\0' */
3321 cstr_ccat(outstr
, '\0');
3323 cstr_wccat(outstr
, '\0');
3326 /* we use 64 bit numbers */
3329 /* bn = (bn << shift) | or_val */
3330 void bn_lshift(unsigned int *bn
, int shift
, int or_val
)
3334 for(i
=0;i
<BN_SIZE
;i
++) {
3336 bn
[i
] = (v
<< shift
) | or_val
;
3337 or_val
= v
>> (32 - shift
);
3341 void bn_zero(unsigned int *bn
)
3344 for(i
=0;i
<BN_SIZE
;i
++) {
3349 /* parse number in null terminated string 'p' and return it in the
3351 void parse_number(const char *p
)
3353 int b
, t
, shift
, frac_bits
, s
, exp_val
, ch
;
3355 unsigned int bn
[BN_SIZE
];
3366 goto float_frac_parse
;
3367 } else if (t
== '0') {
3368 if (ch
== 'x' || ch
== 'X') {
3372 } else if (tcc_ext
&& (ch
== 'b' || ch
== 'B')) {
3378 /* parse all digits. cannot check octal numbers at this stage
3379 because of floating point constants */
3381 if (ch
>= 'a' && ch
<= 'f')
3383 else if (ch
>= 'A' && ch
<= 'F')
3391 if (q
>= token_buf
+ STRING_MAX_SIZE
) {
3393 error("number too long");
3399 ((ch
== 'e' || ch
== 'E') && b
== 10) ||
3400 ((ch
== 'p' || ch
== 'P') && (b
== 16 || b
== 2))) {
3402 /* NOTE: strtox should support that for hexa numbers, but
3403 non ISOC99 libcs do not support it, so we prefer to do
3405 /* hexadecimal or binary floats */
3406 /* XXX: handle overflows */
3418 } else if (t
>= 'a') {
3420 } else if (t
>= 'A') {
3425 bn_lshift(bn
, shift
, t
);
3432 if (t
>= 'a' && t
<= 'f') {
3434 } else if (t
>= 'A' && t
<= 'F') {
3436 } else if (t
>= '0' && t
<= '9') {
3442 error("invalid digit");
3443 bn_lshift(bn
, shift
, t
);
3448 if (ch
!= 'p' && ch
!= 'P')
3455 } else if (ch
== '-') {
3459 if (ch
< '0' || ch
> '9')
3460 expect("exponent digits");
3461 while (ch
>= '0' && ch
<= '9') {
3462 exp_val
= exp_val
* 10 + ch
- '0';
3465 exp_val
= exp_val
* s
;
3467 /* now we can generate the number */
3468 /* XXX: should patch directly float number */
3469 d
= (double)bn
[1] * 4294967296.0 + (double)bn
[0];
3470 d
= ldexp(d
, exp_val
- frac_bits
);
3475 /* float : should handle overflow */
3477 } else if (t
== 'L') {
3480 /* XXX: not large enough */
3481 tokc
.ld
= (long double)d
;
3487 /* decimal floats */
3489 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3494 while (ch
>= '0' && ch
<= '9') {
3495 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3501 if (ch
== 'e' || ch
== 'E') {
3502 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3506 if (ch
== '-' || ch
== '+') {
3507 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3512 if (ch
< '0' || ch
> '9')
3513 expect("exponent digits");
3514 while (ch
>= '0' && ch
<= '9') {
3515 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3527 tokc
.f
= strtof(token_buf
, NULL
);
3528 } else if (t
== 'L') {
3531 tokc
.ld
= strtold(token_buf
, NULL
);
3534 tokc
.d
= strtod(token_buf
, NULL
);
3538 unsigned long long n
, n1
;
3541 /* integer number */
3544 if (b
== 10 && *q
== '0') {
3551 /* no need for checks except for base 10 / 8 errors */
3554 } else if (t
>= 'a') {
3556 } else if (t
>= 'A') {
3561 error("invalid digit");
3565 /* detect overflow */
3566 /* XXX: this test is not reliable */
3568 error("integer constant overflow");
3571 /* XXX: not exactly ANSI compliant */
3572 if ((n
& 0xffffffff00000000LL
) != 0) {
3577 } else if (n
> 0x7fffffff) {
3588 error("three 'l's in integer constant");
3591 if (tok
== TOK_CINT
)
3593 else if (tok
== TOK_CUINT
)
3597 } else if (t
== 'U') {
3599 error("two 'u's in integer constant");
3601 if (tok
== TOK_CINT
)
3603 else if (tok
== TOK_CLLONG
)
3610 if (tok
== TOK_CINT
|| tok
== TOK_CUINT
)
3618 #define PARSE2(c1, tok1, c2, tok2) \
3629 /* return next token without macro substitution */
3630 static inline void next_nomacro1(void)
3650 /* first look if it is in fact an end of buffer */
3651 if (p
>= file
->buf_end
) {
3655 if (p
>= file
->buf_end
)
3668 TCCState
*s1
= tcc_state
;
3669 if ((parse_flags
& PARSE_FLAG_LINEFEED
)
3670 && !(tok_flags
& TOK_FLAG_EOF
)) {
3671 tok_flags
|= TOK_FLAG_EOF
;
3673 goto keep_tok_flags
;
3674 } else if (s1
->include_stack_ptr
== s1
->include_stack
||
3675 !(parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3676 /* no include left : end of file. */
3679 tok_flags
&= ~TOK_FLAG_EOF
;
3680 /* pop include file */
3682 /* test if previous '#endif' was after a #ifdef at
3684 if (tok_flags
& TOK_FLAG_ENDIF
) {
3686 printf("#endif %s\n", get_tok_str(file
->ifndef_macro_saved
, NULL
));
3688 add_cached_include(s1
, file
->inc_type
, file
->inc_filename
,
3689 file
->ifndef_macro_saved
);
3692 /* add end of include file debug info */
3694 put_stabd(N_EINCL
, 0, 0);
3696 /* pop include stack */
3698 s1
->include_stack_ptr
--;
3699 file
= *s1
->include_stack_ptr
;
3708 tok_flags
|= TOK_FLAG_BOL
;
3710 if (0 == (parse_flags
& PARSE_FLAG_LINEFEED
))
3713 goto keep_tok_flags
;
3718 if ((tok_flags
& TOK_FLAG_BOL
) &&
3719 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3721 preprocess(tok_flags
& TOK_FLAG_BOF
);
3727 tok
= TOK_TWOSHARPS
;
3729 if (parse_flags
& PARSE_FLAG_ASM_COMMENTS
) {
3730 p
= parse_line_comment(p
- 1);
3739 case 'a': case 'b': case 'c': case 'd':
3740 case 'e': case 'f': case 'g': case 'h':
3741 case 'i': case 'j': case 'k': case 'l':
3742 case 'm': case 'n': case 'o': case 'p':
3743 case 'q': case 'r': case 's': case 't':
3744 case 'u': case 'v': case 'w': case 'x':
3746 case 'A': case 'B': case 'C': case 'D':
3747 case 'E': case 'F': case 'G': case 'H':
3748 case 'I': case 'J': case 'K':
3749 case 'M': case 'N': case 'O': case 'P':
3750 case 'Q': case 'R': case 'S': case 'T':
3751 case 'U': case 'V': case 'W': case 'X':
3757 h
= TOK_HASH_FUNC(h
, c
);
3761 if (!isidnum_table
[c
])
3763 h
= TOK_HASH_FUNC(h
, c
);
3770 /* fast case : no stray found, so we have the full token
3771 and we have already hashed it */
3773 h
&= (TOK_HASH_SIZE
- 1);
3774 pts
= &hash_ident
[h
];
3779 if (ts
->len
== len
&& !memcmp(ts
->str
, p1
, len
))
3781 pts
= &(ts
->hash_next
);
3783 ts
= tok_alloc_new(pts
, p1
, len
);
3787 cstr_reset(&tokcstr
);
3790 cstr_ccat(&tokcstr
, *p1
);
3796 while (isidnum_table
[c
]) {
3797 cstr_ccat(&tokcstr
, c
);
3800 ts
= tok_alloc(tokcstr
.data
, tokcstr
.size
);
3806 if (t
!= '\\' && t
!= '\'' && t
!= '\"') {
3808 goto parse_ident_fast
;
3811 if (c
== '\'' || c
== '\"') {
3815 cstr_reset(&tokcstr
);
3816 cstr_ccat(&tokcstr
, 'L');
3817 goto parse_ident_slow
;
3821 case '0': case '1': case '2': case '3':
3822 case '4': case '5': case '6': case '7':
3825 cstr_reset(&tokcstr
);
3826 /* after the first digit, accept digits, alpha, '.' or sign if
3827 prefixed by 'eEpP' */
3831 cstr_ccat(&tokcstr
, c
);
3833 if (!(isnum(c
) || isid(c
) || c
== '.' ||
3834 ((c
== '+' || c
== '-') &&
3835 (t
== 'e' || t
== 'E' || t
== 'p' || t
== 'P'))))
3838 /* We add a trailing '\0' to ease parsing */
3839 cstr_ccat(&tokcstr
, '\0');
3840 tokc
.cstr
= &tokcstr
;
3844 /* special dot handling because it can also start a number */
3847 cstr_reset(&tokcstr
);
3848 cstr_ccat(&tokcstr
, '.');
3850 } else if (c
== '.') {
3870 /* parse the string */
3872 p
= parse_pp_string(p
, sep
, &str
);
3873 cstr_ccat(&str
, '\0');
3875 /* eval the escape (should be done as TOK_PPNUM) */
3876 cstr_reset(&tokcstr
);
3877 parse_escape_string(&tokcstr
, str
.data
, is_long
);
3882 /* XXX: make it portable */
3886 char_size
= sizeof(nwchar_t
);
3887 if (tokcstr
.size
<= char_size
)
3888 error("empty character constant");
3889 if (tokcstr
.size
> 2 * char_size
)
3890 warning("multi-character character constant");
3892 tokc
.i
= *(int8_t *)tokcstr
.data
;
3895 tokc
.i
= *(nwchar_t
*)tokcstr
.data
;
3899 tokc
.cstr
= &tokcstr
;
3913 } else if (c
== '<') {
3931 } else if (c
== '>') {
3949 } else if (c
== '=') {
3962 } else if (c
== '=') {
3975 } else if (c
== '=') {
3988 } else if (c
== '=') {
3991 } else if (c
== '>') {
3999 PARSE2('!', '!', '=', TOK_NE
)
4000 PARSE2('=', '=', '=', TOK_EQ
)
4001 PARSE2('*', '*', '=', TOK_A_MUL
)
4002 PARSE2('%', '%', '=', TOK_A_MOD
)
4003 PARSE2('^', '^', '=', TOK_A_XOR
)
4005 /* comments or operator */
4009 p
= parse_comment(p
);
4011 } else if (c
== '/') {
4012 p
= parse_line_comment(p
);
4014 } else if (c
== '=') {
4034 case '$': /* only used in assembler */
4035 case '@': /* dito */
4040 error("unrecognized character \\x%02x", c
);
4046 #if defined(PARSE_DEBUG)
4047 printf("token = %s\n", get_tok_str(tok
, &tokc
));
4051 /* return next token without macro substitution. Can read input from
4053 static void next_nomacro(void)
4059 TOK_GET(tok
, macro_ptr
, tokc
);
4060 if (tok
== TOK_LINENUM
) {
4061 file
->line_num
= tokc
.i
;
4070 /* substitute args in macro_str and return allocated string */
4071 static int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
4073 int *st
, last_tok
, t
, notfirst
;
4082 TOK_GET(t
, macro_str
, cval
);
4087 TOK_GET(t
, macro_str
, cval
);
4090 s
= sym_find2(args
, t
);
4097 cstr_ccat(&cstr
, ' ');
4098 TOK_GET(t
, st
, cval
);
4099 cstr_cat(&cstr
, get_tok_str(t
, &cval
));
4104 cstr_ccat(&cstr
, '\0');
4106 printf("stringize: %s\n", (char *)cstr
.data
);
4110 tok_str_add2(&str
, TOK_STR
, &cval
);
4113 tok_str_add2(&str
, t
, &cval
);
4115 } else if (t
>= TOK_IDENT
) {
4116 s
= sym_find2(args
, t
);
4119 /* if '##' is present before or after, no arg substitution */
4120 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
4121 /* special case for var arg macros : ## eats the
4122 ',' if empty VA_ARGS variable. */
4123 /* XXX: test of the ',' is not 100%
4124 reliable. should fix it to avoid security
4126 if (gnu_ext
&& s
->type
.t
&&
4127 last_tok
== TOK_TWOSHARPS
&&
4128 str
.len
>= 2 && str
.str
[str
.len
- 2] == ',') {
4130 /* suppress ',' '##' */
4133 /* suppress '##' and add variable */
4141 TOK_GET(t1
, st
, cval
);
4144 tok_str_add2(&str
, t1
, &cval
);
4148 /* NOTE: the stream cannot be read when macro
4149 substituing an argument */
4150 macro_subst(&str
, nested_list
, st
, NULL
);
4153 tok_str_add(&str
, t
);
4156 tok_str_add2(&str
, t
, &cval
);
4160 tok_str_add(&str
, 0);
4164 static char const ab_month_name
[12][4] =
4166 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4167 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4170 /* do macro substitution of current token with macro 's' and add
4171 result to (tok_str,tok_len). 'nested_list' is the list of all
4172 macros we got inside to avoid recursing. Return non zero if no
4173 substitution needs to be done */
4174 static int macro_subst_tok(TokenString
*tok_str
,
4175 Sym
**nested_list
, Sym
*s
, struct macro_level
**can_read_stream
)
4177 Sym
*args
, *sa
, *sa1
;
4178 int mstr_allocated
, parlevel
, *mstr
, t
, t1
;
4185 /* if symbol is a macro, prepare substitution */
4186 /* special macros */
4187 if (tok
== TOK___LINE__
) {
4188 snprintf(buf
, sizeof(buf
), "%d", file
->line_num
);
4192 } else if (tok
== TOK___FILE__
) {
4193 cstrval
= file
->filename
;
4195 } else if (tok
== TOK___DATE__
|| tok
== TOK___TIME__
) {
4200 tm
= localtime(&ti
);
4201 if (tok
== TOK___DATE__
) {
4202 snprintf(buf
, sizeof(buf
), "%s %2d %d",
4203 ab_month_name
[tm
->tm_mon
], tm
->tm_mday
, tm
->tm_year
+ 1900);
4205 snprintf(buf
, sizeof(buf
), "%02d:%02d:%02d",
4206 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
);
4213 cstr_cat(&cstr
, cstrval
);
4214 cstr_ccat(&cstr
, '\0');
4216 tok_str_add2(tok_str
, t1
, &cval
);
4221 if (s
->type
.t
== MACRO_FUNC
) {
4222 /* NOTE: we do not use next_nomacro to avoid eating the
4223 next token. XXX: find better solution */
4227 if (t
== 0 && can_read_stream
) {
4228 /* end of macro stream: we must look at the token
4229 after in the file */
4230 struct macro_level
*ml
= *can_read_stream
;
4236 *can_read_stream
= ml
-> prev
;
4241 /* XXX: incorrect with comments */
4242 ch
= file
->buf_ptr
[0];
4243 while (is_space(ch
) || ch
== '\n')
4247 if (t
!= '(') /* no macro subst */
4250 /* argument macro */
4255 /* NOTE: empty args are allowed, except if no args */
4257 /* handle '()' case */
4258 if (!args
&& !sa
&& tok
== ')')
4261 error("macro '%s' used with too many args",
4262 get_tok_str(s
->v
, 0));
4265 /* NOTE: non zero sa->t indicates VA_ARGS */
4266 while ((parlevel
> 0 ||
4268 (tok
!= ',' || sa
->type
.t
))) &&
4272 else if (tok
== ')')
4274 if (tok
!= TOK_LINEFEED
)
4275 tok_str_add2(&str
, tok
, &tokc
);
4278 tok_str_add(&str
, 0);
4279 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, sa
->type
.t
, (int)str
.str
);
4282 /* special case for gcc var args: add an empty
4283 var arg argument if it is omitted */
4284 if (sa
&& sa
->type
.t
&& gnu_ext
)
4294 error("macro '%s' used with too few args",
4295 get_tok_str(s
->v
, 0));
4298 /* now subst each arg */
4299 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
4304 tok_str_free((int *)sa
->c
);
4310 sym_push2(nested_list
, s
->v
, 0, 0);
4311 macro_subst(tok_str
, nested_list
, mstr
, can_read_stream
);
4312 /* pop nested defined symbol */
4314 *nested_list
= sa1
->prev
;
4322 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4323 return the resulting string (which must be freed). */
4324 static inline int *macro_twosharps(const int *macro_str
)
4327 const int *macro_ptr1
, *start_macro_ptr
, *ptr
, *saved_macro_ptr
;
4329 const char *p1
, *p2
;
4331 TokenString macro_str1
;
4334 start_macro_ptr
= macro_str
;
4335 /* we search the first '##' */
4337 macro_ptr1
= macro_str
;
4338 TOK_GET(t
, macro_str
, cval
);
4339 /* nothing more to do if end of string */
4342 if (*macro_str
== TOK_TWOSHARPS
)
4346 /* we saw '##', so we need more processing to handle it */
4348 tok_str_new(¯o_str1
);
4352 /* add all tokens seen so far */
4353 for(ptr
= start_macro_ptr
; ptr
< macro_ptr1
;) {
4354 TOK_GET(t
, ptr
, cval
);
4355 tok_str_add2(¯o_str1
, t
, &cval
);
4357 saved_macro_ptr
= macro_ptr
;
4358 /* XXX: get rid of the use of macro_ptr here */
4359 macro_ptr
= (int *)macro_str
;
4361 while (*macro_ptr
== TOK_TWOSHARPS
) {
4363 macro_ptr1
= macro_ptr
;
4366 TOK_GET(t
, macro_ptr
, cval
);
4367 /* We concatenate the two tokens if we have an
4368 identifier or a preprocessing number */
4370 p1
= get_tok_str(tok
, &tokc
);
4371 cstr_cat(&cstr
, p1
);
4372 p2
= get_tok_str(t
, &cval
);
4373 cstr_cat(&cstr
, p2
);
4374 cstr_ccat(&cstr
, '\0');
4376 if ((tok
>= TOK_IDENT
|| tok
== TOK_PPNUM
) &&
4377 (t
>= TOK_IDENT
|| t
== TOK_PPNUM
)) {
4378 if (tok
== TOK_PPNUM
) {
4379 /* if number, then create a number token */
4380 /* NOTE: no need to allocate because
4381 tok_str_add2() does it */
4382 cstr_reset(&tokcstr
);
4385 tokc
.cstr
= &tokcstr
;
4387 /* if identifier, we must do a test to
4388 validate we have a correct identifier */
4389 if (t
== TOK_PPNUM
) {
4399 if (!isnum(c
) && !isid(c
))
4403 ts
= tok_alloc(cstr
.data
, strlen(cstr
.data
));
4404 tok
= ts
->tok
; /* modify current token */
4407 const char *str
= cstr
.data
;
4408 const unsigned char *q
;
4410 /* we look for a valid token */
4411 /* XXX: do more extensive checks */
4412 if (!strcmp(str
, ">>=")) {
4414 } else if (!strcmp(str
, "<<=")) {
4416 } else if (strlen(str
) == 2) {
4417 /* search in two bytes table */
4422 if (q
[0] == str
[0] && q
[1] == str
[1])
4429 /* NOTE: because get_tok_str use a static buffer,
4432 p1
= get_tok_str(tok
, &tokc
);
4433 cstr_cat(&cstr
, p1
);
4434 cstr_ccat(&cstr
, '\0');
4435 p2
= get_tok_str(t
, &cval
);
4436 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr
.data
, p2
);
4437 /* cannot merge tokens: just add them separately */
4438 tok_str_add2(¯o_str1
, tok
, &tokc
);
4439 /* XXX: free associated memory ? */
4446 tok_str_add2(¯o_str1
, tok
, &tokc
);
4451 macro_ptr
= (int *)saved_macro_ptr
;
4453 tok_str_add(¯o_str1
, 0);
4454 return macro_str1
.str
;
4458 /* do macro substitution of macro_str and add result to
4459 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4460 inside to avoid recursing. */
4461 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
4462 const int *macro_str
, struct macro_level
** can_read_stream
)
4469 struct macro_level ml
;
4471 /* first scan for '##' operator handling */
4473 macro_str1
= macro_twosharps(ptr
);
4477 /* NOTE: ptr == NULL can only happen if tokens are read from
4478 file stream due to a macro function call */
4481 TOK_GET(t
, ptr
, cval
);
4486 /* if nested substitution, do nothing */
4487 if (sym_find2(*nested_list
, t
))
4490 if (can_read_stream
)
4491 ml
.prev
= *can_read_stream
, *can_read_stream
= &ml
;
4492 macro_ptr
= (int *)ptr
;
4494 ret
= macro_subst_tok(tok_str
, nested_list
, s
, can_read_stream
);
4495 ptr
= (int *)macro_ptr
;
4497 if (can_read_stream
&& *can_read_stream
== &ml
)
4498 *can_read_stream
= ml
.prev
;
4503 tok_str_add2(tok_str
, t
, &cval
);
4507 tok_str_free(macro_str1
);
4510 /* return next token with macro substitution */
4511 static void next(void)
4513 Sym
*nested_list
, *s
;
4515 struct macro_level
*ml
;
4520 /* if not reading from macro substituted string, then try
4521 to substitute macros */
4522 if (tok
>= TOK_IDENT
&&
4523 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
4524 s
= define_find(tok
);
4526 /* we have a macro: we try to substitute */
4530 if (macro_subst_tok(&str
, &nested_list
, s
, &ml
) == 0) {
4531 /* substitution done, NOTE: maybe empty */
4532 tok_str_add(&str
, 0);
4533 macro_ptr
= str
.str
;
4534 macro_ptr_allocated
= str
.str
;
4541 /* end of macro or end of unget buffer */
4542 if (unget_buffer_enabled
) {
4543 macro_ptr
= unget_saved_macro_ptr
;
4544 unget_buffer_enabled
= 0;
4546 /* end of macro string: free it */
4547 tok_str_free(macro_ptr_allocated
);
4554 /* convert preprocessor tokens into C tokens */
4555 if (tok
== TOK_PPNUM
&&
4556 (parse_flags
& PARSE_FLAG_TOK_NUM
)) {
4557 parse_number((char *)tokc
.cstr
->data
);
4561 /* push back current token and set current token to 'last_tok'. Only
4562 identifier case handled for labels. */
4563 static inline void unget_tok(int last_tok
)
4567 unget_saved_macro_ptr
= macro_ptr
;
4568 unget_buffer_enabled
= 1;
4569 q
= unget_saved_buffer
;
4572 n
= tok_ext_size(tok
) - 1;
4575 *q
= 0; /* end of token string */
4580 void swap(int *p
, int *q
)
4588 void vsetc(CType
*type
, int r
, CValue
*vc
)
4592 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4593 error("memory full");
4594 /* cannot let cpu flags if other instruction are generated. Also
4595 avoid leaving VT_JMP anywhere except on the top of the stack
4596 because it would complicate the code generator. */
4597 if (vtop
>= vstack
) {
4598 v
= vtop
->r
& VT_VALMASK
;
4599 if (v
== VT_CMP
|| (v
& ~1) == VT_JMP
)
4605 vtop
->r2
= VT_CONST
;
4609 /* push integer constant */
4614 vsetc(&int_type
, VT_CONST
, &cval
);
4617 /* Return a static symbol pointing to a section */
4618 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
4619 unsigned long offset
, unsigned long size
)
4625 sym
= global_identifier_push(v
, type
->t
| VT_STATIC
, 0);
4626 sym
->type
.ref
= type
->ref
;
4627 sym
->r
= VT_CONST
| VT_SYM
;
4628 put_extern_sym(sym
, sec
, offset
, size
);
4632 /* push a reference to a section offset by adding a dummy symbol */
4633 static void vpush_ref(CType
*type
, Section
*sec
, unsigned long offset
, unsigned long size
)
4638 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4639 vtop
->sym
= get_sym_ref(type
, sec
, offset
, size
);
4642 /* define a new external reference to a symbol 'v' of type 'u' */
4643 static Sym
*external_global_sym(int v
, CType
*type
, int r
)
4649 /* push forward reference */
4650 s
= global_identifier_push(v
, type
->t
| VT_EXTERN
, 0);
4651 s
->type
.ref
= type
->ref
;
4652 s
->r
= r
| VT_CONST
| VT_SYM
;
4657 /* define a new external reference to a symbol 'v' of type 'u' */
4658 static Sym
*external_sym(int v
, CType
*type
, int r
)
4664 /* push forward reference */
4665 s
= sym_push(v
, type
, r
| VT_CONST
| VT_SYM
, 0);
4666 s
->type
.t
|= VT_EXTERN
;
4668 if (!is_compatible_types(&s
->type
, type
))
4669 error("incompatible types for redefinition of '%s'",
4670 get_tok_str(v
, NULL
));
4675 /* push a reference to global symbol v */
4676 static void vpush_global_sym(CType
*type
, int v
)
4681 sym
= external_global_sym(v
, type
, 0);
4683 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4687 void vset(CType
*type
, int r
, int v
)
4692 vsetc(type
, r
, &cval
);
4695 void vseti(int r
, int v
)
4711 void vpushv(SValue
*v
)
4713 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4714 error("memory full");
4724 /* save r to the memory stack, and mark it as being free */
4725 void save_reg(int r
)
4727 int l
, saved
, size
, align
;
4731 /* modify all stack values */
4734 for(p
=vstack
;p
<=vtop
;p
++) {
4735 if ((p
->r
& VT_VALMASK
) == r
||
4736 ((p
->type
.t
& VT_BTYPE
) == VT_LLONG
&& (p
->r2
& VT_VALMASK
) == r
)) {
4737 /* must save value on stack if not already done */
4739 /* NOTE: must reload 'r' because r might be equal to r2 */
4740 r
= p
->r
& VT_VALMASK
;
4741 /* store register in the stack */
4743 if ((p
->r
& VT_LVAL
) ||
4744 (!is_float(type
->t
) && (type
->t
& VT_BTYPE
) != VT_LLONG
))
4746 size
= type_size(type
, &align
);
4747 loc
= (loc
- size
) & -align
;
4748 sv
.type
.t
= type
->t
;
4749 sv
.r
= VT_LOCAL
| VT_LVAL
;
4752 #ifdef TCC_TARGET_I386
4753 /* x86 specific: need to pop fp register ST0 if saved */
4754 if (r
== TREG_ST0
) {
4755 o(0xd9dd); /* fstp %st(1) */
4758 /* special long long case */
4759 if ((type
->t
& VT_BTYPE
) == VT_LLONG
) {
4766 /* mark that stack entry as being saved on the stack */
4767 if (p
->r
& VT_LVAL
) {
4768 /* also clear the bounded flag because the
4769 relocation address of the function was stored in
4771 p
->r
= (p
->r
& ~(VT_VALMASK
| VT_BOUNDED
)) | VT_LLOCAL
;
4773 p
->r
= lvalue_type(p
->type
.t
) | VT_LOCAL
;
4781 /* find a register of class 'rc2' with at most one reference on stack.
4782 * If none, call get_reg(rc) */
4783 int get_reg_ex(int rc
, int rc2
)
4788 for(r
=0;r
<NB_REGS
;r
++) {
4789 if (reg_classes
[r
] & rc2
) {
4792 for(p
= vstack
; p
<= vtop
; p
++) {
4793 if ((p
->r
& VT_VALMASK
) == r
||
4794 (p
->r2
& VT_VALMASK
) == r
)
4804 /* find a free register of class 'rc'. If none, save one register */
4810 /* find a free register */
4811 for(r
=0;r
<NB_REGS
;r
++) {
4812 if (reg_classes
[r
] & rc
) {
4813 for(p
=vstack
;p
<=vtop
;p
++) {
4814 if ((p
->r
& VT_VALMASK
) == r
||
4815 (p
->r2
& VT_VALMASK
) == r
)
4823 /* no register left : free the first one on the stack (VERY
4824 IMPORTANT to start from the bottom to ensure that we don't
4825 spill registers used in gen_opi()) */
4826 for(p
=vstack
;p
<=vtop
;p
++) {
4827 r
= p
->r
& VT_VALMASK
;
4828 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
))
4830 /* also look at second register (if long long) */
4831 r
= p
->r2
& VT_VALMASK
;
4832 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
4838 /* Should never comes here */
4842 /* save registers up to (vtop - n) stack entry */
4843 void save_regs(int n
)
4848 for(p
= vstack
;p
<= p1
; p
++) {
4849 r
= p
->r
& VT_VALMASK
;
4856 /* move register 's' to 'r', and flush previous value of r to memory
4858 void move_reg(int r
, int s
)
4871 /* get address of vtop (vtop MUST BE an lvalue) */
4874 vtop
->r
&= ~VT_LVAL
;
4875 /* tricky: if saved lvalue, then we can go back to lvalue */
4876 if ((vtop
->r
& VT_VALMASK
) == VT_LLOCAL
)
4877 vtop
->r
= (vtop
->r
& ~(VT_VALMASK
| VT_LVAL_TYPE
)) | VT_LOCAL
| VT_LVAL
;
4880 #ifdef CONFIG_TCC_BCHECK
4881 /* generate lvalue bound code */
4887 vtop
->r
&= ~VT_MUSTBOUND
;
4888 /* if lvalue, then use checking code before dereferencing */
4889 if (vtop
->r
& VT_LVAL
) {
4890 /* if not VT_BOUNDED value, then make one */
4891 if (!(vtop
->r
& VT_BOUNDED
)) {
4892 lval_type
= vtop
->r
& (VT_LVAL_TYPE
| VT_LVAL
);
4893 /* must save type because we must set it to int to get pointer */
4895 vtop
->type
.t
= VT_INT
;
4898 gen_bounded_ptr_add();
4899 vtop
->r
|= lval_type
;
4902 /* then check for dereferencing */
4903 gen_bounded_ptr_deref();
4908 /* store vtop a register belonging to class 'rc'. lvalues are
4909 converted to values. Cannot be used if cannot be converted to
4910 register value (such as structures). */
4913 int r
, r2
, rc2
, bit_pos
, bit_size
, size
, align
, i
;
4914 unsigned long long ll
;
4916 /* NOTE: get_reg can modify vstack[] */
4917 if (vtop
->type
.t
& VT_BITFIELD
) {
4918 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
4919 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
4920 /* remove bit field info to avoid loops */
4921 vtop
->type
.t
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
4922 /* generate shifts */
4923 vpushi(32 - (bit_pos
+ bit_size
));
4925 vpushi(32 - bit_size
);
4926 /* NOTE: transformed to SHR if unsigned */
4930 if (is_float(vtop
->type
.t
) &&
4931 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4934 unsigned long offset
;
4935 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4939 /* XXX: unify with initializers handling ? */
4940 /* CPUs usually cannot use float constants, so we store them
4941 generically in data segment */
4942 size
= type_size(&vtop
->type
, &align
);
4943 offset
= (data_section
->data_offset
+ align
- 1) & -align
;
4944 data_section
->data_offset
= offset
;
4945 /* XXX: not portable yet */
4947 /* Zero pad x87 tenbyte long doubles */
4949 vtop
->c
.tab
[2] &= 0xffff;
4951 ptr
= section_ptr_add(data_section
, size
);
4953 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4957 ptr
[i
] = vtop
->c
.tab
[size
-1-i
];
4961 ptr
[i
] = vtop
->c
.tab
[i
];
4962 sym
= get_sym_ref(&vtop
->type
, data_section
, offset
, size
<< 2);
4963 vtop
->r
|= VT_LVAL
| VT_SYM
;
4967 #ifdef CONFIG_TCC_BCHECK
4968 if (vtop
->r
& VT_MUSTBOUND
)
4972 r
= vtop
->r
& VT_VALMASK
;
4973 /* need to reload if:
4975 - lvalue (need to dereference pointer)
4976 - already a register, but not in the right class */
4977 if (r
>= VT_CONST
||
4978 (vtop
->r
& VT_LVAL
) ||
4979 !(reg_classes
[r
] & rc
) ||
4980 ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
&&
4981 !(reg_classes
[vtop
->r2
] & rc
))) {
4983 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
4984 /* two register type load : expand to two words
4986 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4989 vtop
->c
.ui
= ll
; /* first word */
4991 vtop
->r
= r
; /* save register value */
4992 vpushi(ll
>> 32); /* second word */
4993 } else if (r
>= VT_CONST
|| /* XXX: test to VT_CONST incorrect ? */
4994 (vtop
->r
& VT_LVAL
)) {
4995 /* We do not want to modifier the long long
4996 pointer here, so the safest (and less
4997 efficient) is to save all the other registers
4998 in the stack. XXX: totally inefficient. */
5000 /* load from memory */
5003 vtop
[-1].r
= r
; /* save register value */
5004 /* increment pointer to get second word */
5005 vtop
->type
.t
= VT_INT
;
5011 /* move registers */
5014 vtop
[-1].r
= r
; /* save register value */
5015 vtop
->r
= vtop
[-1].r2
;
5017 /* allocate second register */
5024 /* write second register */
5026 } else if ((vtop
->r
& VT_LVAL
) && !is_float(vtop
->type
.t
)) {
5028 /* lvalue of scalar type : need to use lvalue type
5029 because of possible cast */
5032 /* compute memory access type */
5033 if (vtop
->r
& VT_LVAL_BYTE
)
5035 else if (vtop
->r
& VT_LVAL_SHORT
)
5037 if (vtop
->r
& VT_LVAL_UNSIGNED
)
5041 /* restore wanted type */
5044 /* one register type load */
5049 #ifdef TCC_TARGET_C67
5050 /* uses register pairs for doubles */
5051 if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
)
5058 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
5059 void gv2(int rc1
, int rc2
)
5063 /* generate more generic register first. But VT_JMP or VT_CMP
5064 values must be generated first in all cases to avoid possible
5066 v
= vtop
[0].r
& VT_VALMASK
;
5067 if (v
!= VT_CMP
&& (v
& ~1) != VT_JMP
&& rc1
<= rc2
) {
5072 /* test if reload is needed for first register */
5073 if ((vtop
[-1].r
& VT_VALMASK
) >= VT_CONST
) {
5083 /* test if reload is needed for first register */
5084 if ((vtop
[0].r
& VT_VALMASK
) >= VT_CONST
) {
5090 /* expand long long on stack in two int registers */
5095 u
= vtop
->type
.t
& VT_UNSIGNED
;
5098 vtop
[0].r
= vtop
[-1].r2
;
5099 vtop
[0].r2
= VT_CONST
;
5100 vtop
[-1].r2
= VT_CONST
;
5101 vtop
[0].type
.t
= VT_INT
| u
;
5102 vtop
[-1].type
.t
= VT_INT
| u
;
5105 #ifdef TCC_TARGET_ARM
5106 /* expand long long on stack */
5107 void lexpand_nr(void)
5111 u
= vtop
->type
.t
& VT_UNSIGNED
;
5113 vtop
->r2
= VT_CONST
;
5114 vtop
->type
.t
= VT_INT
| u
;
5115 v
=vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
);
5116 if (v
== VT_CONST
) {
5117 vtop
[-1].c
.ui
= vtop
->c
.ull
;
5118 vtop
->c
.ui
= vtop
->c
.ull
>> 32;
5120 } else if (v
== (VT_LVAL
|VT_CONST
) || v
== (VT_LVAL
|VT_LOCAL
)) {
5122 vtop
->r
= vtop
[-1].r
;
5123 } else if (v
> VT_CONST
) {
5127 vtop
->r
= vtop
[-1].r2
;
5128 vtop
[-1].r2
= VT_CONST
;
5129 vtop
[-1].type
.t
= VT_INT
| u
;
5133 /* build a long long from two ints */
5136 gv2(RC_INT
, RC_INT
);
5137 vtop
[-1].r2
= vtop
[0].r
;
5138 vtop
[-1].type
.t
= t
;
5142 /* rotate n first stack elements to the bottom
5143 I1 ... In -> I2 ... In I1 [top is right]
5151 for(i
=-n
+1;i
!=0;i
++)
5152 vtop
[i
] = vtop
[i
+1];
5156 /* rotate n first stack elements to the top
5157 I1 ... In -> In I1 ... I(n-1) [top is right]
5165 for(i
= 0;i
< n
- 1; i
++)
5166 vtop
[-i
] = vtop
[-i
- 1];
5170 #ifdef TCC_TARGET_ARM
5171 /* like vrott but in other direction
5172 In ... I1 -> I(n-1) ... I1 In [top is right]
5180 for(i
= n
- 1; i
> 0; i
--)
5181 vtop
[-i
] = vtop
[-i
+ 1];
5186 /* pop stack value */
5190 v
= vtop
->r
& VT_VALMASK
;
5191 #ifdef TCC_TARGET_I386
5192 /* for x86, we need to pop the FP stack */
5193 if (v
== TREG_ST0
&& !nocode_wanted
) {
5194 o(0xd9dd); /* fstp %st(1) */
5197 if (v
== VT_JMP
|| v
== VT_JMPI
) {
5198 /* need to put correct jump if && or || without test */
5204 /* convert stack entry to register and duplicate its value in another
5212 if ((t
& VT_BTYPE
) == VT_LLONG
) {
5219 /* stack: H L L1 H1 */
5227 /* duplicate value */
5238 load(r1
, &sv
); /* move r to r1 */
5240 /* duplicates value */
5245 /* generate CPU independent (unsigned) long long operations */
5246 void gen_opl(int op
)
5248 int t
, a
, b
, op1
, c
, i
;
5255 func
= TOK___divdi3
;
5258 func
= TOK___udivdi3
;
5261 func
= TOK___moddi3
;
5264 func
= TOK___umoddi3
;
5266 /* call generic long long function */
5267 vpush_global_sym(&func_old_type
, func
);
5272 vtop
->r2
= REG_LRET
;
5285 /* stack: L1 H1 L2 H2 */
5290 vtop
[-2] = vtop
[-3];
5293 /* stack: H1 H2 L1 L2 */
5299 /* stack: H1 H2 L1 L2 ML MH */
5302 /* stack: ML MH H1 H2 L1 L2 */
5306 /* stack: ML MH H1 L2 H2 L1 */
5311 /* stack: ML MH M1 M2 */
5314 } else if (op
== '+' || op
== '-') {
5315 /* XXX: add non carry method too (for MIPS or alpha) */
5321 /* stack: H1 H2 (L1 op L2) */
5324 gen_op(op1
+ 1); /* TOK_xxxC2 */
5327 /* stack: H1 H2 (L1 op L2) */
5330 /* stack: (L1 op L2) H1 H2 */
5332 /* stack: (L1 op L2) (H1 op H2) */
5340 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
5341 t
= vtop
[-1].type
.t
;
5345 /* stack: L H shift */
5347 /* constant: simpler */
5348 /* NOTE: all comments are for SHL. the other cases are
5349 done by swaping words */
5360 if (op
!= TOK_SAR
) {
5393 /* XXX: should provide a faster fallback on x86 ? */
5396 func
= TOK___sardi3
;
5399 func
= TOK___shrdi3
;
5402 func
= TOK___shldi3
;
5408 /* compare operations */
5414 /* stack: L1 H1 L2 H2 */
5416 vtop
[-1] = vtop
[-2];
5418 /* stack: L1 L2 H1 H2 */
5421 /* when values are equal, we need to compare low words. since
5422 the jump is inverted, we invert the test too. */
5425 else if (op1
== TOK_GT
)
5427 else if (op1
== TOK_ULT
)
5429 else if (op1
== TOK_UGT
)
5434 if (op1
!= TOK_NE
) {
5438 /* generate non equal test */
5439 /* XXX: NOT PORTABLE yet */
5443 #if defined(TCC_TARGET_I386)
5444 b
= psym(0x850f, 0);
5445 #elif defined(TCC_TARGET_ARM)
5447 o(0x1A000000 | encbranch(ind
, 0, 1));
5448 #elif defined(TCC_TARGET_C67)
5449 error("not implemented");
5451 #error not supported
5455 /* compare low. Always unsigned */
5459 else if (op1
== TOK_LE
)
5461 else if (op1
== TOK_GT
)
5463 else if (op1
== TOK_GE
)
5473 /* handle integer constant optimizations and various machine
5475 void gen_opic(int op
)
5477 int c1
, c2
, t1
, t2
, n
;
5480 typedef unsigned long long U
;
5484 t1
= v1
->type
.t
& VT_BTYPE
;
5485 t2
= v2
->type
.t
& VT_BTYPE
;
5486 l1
= (t1
== VT_LLONG
) ? v1
->c
.ll
: v1
->c
.i
;
5487 l2
= (t2
== VT_LLONG
) ? v2
->c
.ll
: v2
->c
.i
;
5489 /* currently, we cannot do computations with forward symbols */
5490 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5491 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5494 case '+': l1
+= l2
; break;
5495 case '-': l1
-= l2
; break;
5496 case '&': l1
&= l2
; break;
5497 case '^': l1
^= l2
; break;
5498 case '|': l1
|= l2
; break;
5499 case '*': l1
*= l2
; break;
5506 /* if division by zero, generate explicit division */
5509 error("division by zero in constant");
5513 default: l1
/= l2
; break;
5514 case '%': l1
%= l2
; break;
5515 case TOK_UDIV
: l1
= (U
)l1
/ l2
; break;
5516 case TOK_UMOD
: l1
= (U
)l1
% l2
; break;
5519 case TOK_SHL
: l1
<<= l2
; break;
5520 case TOK_SHR
: l1
= (U
)l1
>> l2
; break;
5521 case TOK_SAR
: l1
>>= l2
; break;
5523 case TOK_ULT
: l1
= (U
)l1
< (U
)l2
; break;
5524 case TOK_UGE
: l1
= (U
)l1
>= (U
)l2
; break;
5525 case TOK_EQ
: l1
= l1
== l2
; break;
5526 case TOK_NE
: l1
= l1
!= l2
; break;
5527 case TOK_ULE
: l1
= (U
)l1
<= (U
)l2
; break;
5528 case TOK_UGT
: l1
= (U
)l1
> (U
)l2
; break;
5529 case TOK_LT
: l1
= l1
< l2
; break;
5530 case TOK_GE
: l1
= l1
>= l2
; break;
5531 case TOK_LE
: l1
= l1
<= l2
; break;
5532 case TOK_GT
: l1
= l1
> l2
; break;
5534 case TOK_LAND
: l1
= l1
&& l2
; break;
5535 case TOK_LOR
: l1
= l1
|| l2
; break;
5542 /* if commutative ops, put c2 as constant */
5543 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
5544 op
== '|' || op
== '*')) {
5546 c2
= c1
; //c = c1, c1 = c2, c2 = c;
5547 l2
= l1
; //l = l1, l1 = l2, l2 = l;
5549 /* Filter out NOP operations like x*1, x-0, x&-1... */
5550 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
5553 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
5554 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
5560 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
5561 /* try to use shifts instead of muls or divs */
5562 if (l2
> 0 && (l2
& (l2
- 1)) == 0) {
5571 else if (op
== TOK_PDIV
)
5577 } else if (c2
&& (op
== '+' || op
== '-') &&
5578 (vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) ==
5579 (VT_CONST
| VT_SYM
)) {
5580 /* symbol + constant case */
5587 if (!nocode_wanted
) {
5588 /* call low level op generator */
5589 if (t1
== VT_LLONG
|| t2
== VT_LLONG
)
5600 /* generate a floating point operation with constant propagation */
5601 void gen_opif(int op
)
5609 /* currently, we cannot do computations with forward symbols */
5610 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5611 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5613 if (v1
->type
.t
== VT_FLOAT
) {
5616 } else if (v1
->type
.t
== VT_DOUBLE
) {
5624 /* NOTE: we only do constant propagation if finite number (not
5625 NaN or infinity) (ANSI spec) */
5626 if (!ieee_finite(f1
) || !ieee_finite(f2
))
5630 case '+': f1
+= f2
; break;
5631 case '-': f1
-= f2
; break;
5632 case '*': f1
*= f2
; break;
5636 error("division by zero in constant");
5641 /* XXX: also handles tests ? */
5645 /* XXX: overflow test ? */
5646 if (v1
->type
.t
== VT_FLOAT
) {
5648 } else if (v1
->type
.t
== VT_DOUBLE
) {
5656 if (!nocode_wanted
) {
5664 static int pointed_size(CType
*type
)
5667 return type_size(pointed_type(type
), &align
);
5670 static inline int is_null_pointer(SValue
*p
)
5672 if ((p
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
5674 return ((p
->type
.t
& VT_BTYPE
) == VT_INT
&& p
->c
.i
== 0) ||
5675 ((p
->type
.t
& VT_BTYPE
) == VT_LLONG
&& p
->c
.ll
== 0);
5678 static inline int is_integer_btype(int bt
)
5680 return (bt
== VT_BYTE
|| bt
== VT_SHORT
||
5681 bt
== VT_INT
|| bt
== VT_LLONG
);
5684 /* check types for comparison or substraction of pointers */
5685 static void check_comparison_pointer_types(SValue
*p1
, SValue
*p2
, int op
)
5687 CType
*type1
, *type2
, tmp_type1
, tmp_type2
;
5690 /* null pointers are accepted for all comparisons as gcc */
5691 if (is_null_pointer(p1
) || is_null_pointer(p2
))
5695 bt1
= type1
->t
& VT_BTYPE
;
5696 bt2
= type2
->t
& VT_BTYPE
;
5697 /* accept comparison between pointer and integer with a warning */
5698 if ((is_integer_btype(bt1
) || is_integer_btype(bt2
)) && op
!= '-') {
5699 if (op
!= TOK_LOR
&& op
!= TOK_LAND
)
5700 warning("comparison between pointer and integer");
5704 /* both must be pointers or implicit function pointers */
5705 if (bt1
== VT_PTR
) {
5706 type1
= pointed_type(type1
);
5707 } else if (bt1
!= VT_FUNC
)
5708 goto invalid_operands
;
5710 if (bt2
== VT_PTR
) {
5711 type2
= pointed_type(type2
);
5712 } else if (bt2
!= VT_FUNC
) {
5714 error("invalid operands to binary %s", get_tok_str(op
, NULL
));
5716 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
5717 (type2
->t
& VT_BTYPE
) == VT_VOID
)
5721 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5722 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5723 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
5724 /* gcc-like error if '-' is used */
5726 goto invalid_operands
;
5728 warning("comparison of distinct pointer types lacks a cast");
5732 /* generic gen_op: handles types problems */
5735 int u
, t1
, t2
, bt1
, bt2
, t
;
5738 t1
= vtop
[-1].type
.t
;
5739 t2
= vtop
[0].type
.t
;
5740 bt1
= t1
& VT_BTYPE
;
5741 bt2
= t2
& VT_BTYPE
;
5743 if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
5744 /* at least one operand is a pointer */
5745 /* relationnal op: must be both pointers */
5746 if (op
>= TOK_ULT
&& op
<= TOK_LOR
) {
5747 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5748 /* pointers are handled are unsigned */
5749 t
= VT_INT
| VT_UNSIGNED
;
5752 /* if both pointers, then it must be the '-' op */
5753 if (bt1
== VT_PTR
&& bt2
== VT_PTR
) {
5755 error("cannot use pointers here");
5756 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5757 /* XXX: check that types are compatible */
5758 u
= pointed_size(&vtop
[-1].type
);
5760 /* set to integer type */
5761 vtop
->type
.t
= VT_INT
;
5765 /* exactly one pointer : must be '+' or '-'. */
5766 if (op
!= '-' && op
!= '+')
5767 error("cannot use pointers here");
5768 /* Put pointer as first operand */
5769 if (bt2
== VT_PTR
) {
5773 type1
= vtop
[-1].type
;
5774 /* XXX: cast to int ? (long long case) */
5775 vpushi(pointed_size(&vtop
[-1].type
));
5777 #ifdef CONFIG_TCC_BCHECK
5778 /* if evaluating constant expression, no code should be
5779 generated, so no bound check */
5780 if (do_bounds_check
&& !const_wanted
) {
5781 /* if bounded pointers, we generate a special code to
5788 gen_bounded_ptr_add();
5794 /* put again type if gen_opic() swaped operands */
5797 } else if (is_float(bt1
) || is_float(bt2
)) {
5798 /* compute bigger type and do implicit casts */
5799 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
5801 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
5806 /* floats can only be used for a few operations */
5807 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
5808 (op
< TOK_ULT
|| op
> TOK_GT
))
5809 error("invalid operands for binary operation");
5811 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
5812 /* cast to biggest op */
5814 /* convert to unsigned if it does not fit in a long long */
5815 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
5816 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
5820 /* integer operations */
5822 /* convert to unsigned if it does not fit in an integer */
5823 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
5824 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
5827 /* XXX: currently, some unsigned operations are explicit, so
5828 we modify them here */
5829 if (t
& VT_UNSIGNED
) {
5836 else if (op
== TOK_LT
)
5838 else if (op
== TOK_GT
)
5840 else if (op
== TOK_LE
)
5842 else if (op
== TOK_GE
)
5849 /* special case for shifts and long long: we keep the shift as
5851 if (op
== TOK_SHR
|| op
== TOK_SAR
|| op
== TOK_SHL
)
5858 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
5859 /* relationnal op: the result is an int */
5860 vtop
->type
.t
= VT_INT
;
5867 /* generic itof for unsigned long long case */
5868 void gen_cvt_itof1(int t
)
5870 if ((vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
)) ==
5871 (VT_LLONG
| VT_UNSIGNED
)) {
5874 vpush_global_sym(&func_old_type
, TOK___ulltof
);
5875 else if (t
== VT_DOUBLE
)
5876 vpush_global_sym(&func_old_type
, TOK___ulltod
);
5878 vpush_global_sym(&func_old_type
, TOK___ulltold
);
5888 /* generic ftoi for unsigned long long case */
5889 void gen_cvt_ftoi1(int t
)
5893 if (t
== (VT_LLONG
| VT_UNSIGNED
)) {
5894 /* not handled natively */
5895 st
= vtop
->type
.t
& VT_BTYPE
;
5897 vpush_global_sym(&func_old_type
, TOK___fixunssfdi
);
5898 else if (st
== VT_DOUBLE
)
5899 vpush_global_sym(&func_old_type
, TOK___fixunsdfdi
);
5901 vpush_global_sym(&func_old_type
, TOK___fixunsxfdi
);
5906 vtop
->r2
= REG_LRET
;
5912 /* force char or short cast */
5913 void force_charshort_cast(int t
)
5917 /* XXX: add optimization if lvalue : just change type and offset */
5922 if (t
& VT_UNSIGNED
) {
5923 vpushi((1 << bits
) - 1);
5929 /* result must be signed or the SAR is converted to an SHL
5930 This was not the case when "t" was a signed short
5931 and the last value on the stack was an unsigned int */
5932 vtop
->type
.t
&= ~VT_UNSIGNED
;
5938 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5939 static void gen_cast(CType
*type
)
5941 int sbt
, dbt
, sf
, df
, c
;
5943 /* special delayed cast for char/short */
5944 /* XXX: in some cases (multiple cascaded casts), it may still
5946 if (vtop
->r
& VT_MUSTCAST
) {
5947 vtop
->r
&= ~VT_MUSTCAST
;
5948 force_charshort_cast(vtop
->type
.t
);
5951 /* bitfields first get cast to ints */
5952 if (vtop
->type
.t
& VT_BITFIELD
) {
5956 dbt
= type
->t
& (VT_BTYPE
| VT_UNSIGNED
);
5957 sbt
= vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
);
5959 if (sbt
!= dbt
&& !nocode_wanted
) {
5962 c
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5964 /* convert from fp to fp */
5966 /* constant case: we can do it now */
5967 /* XXX: in ISOC, cannot do it if error in convert */
5968 if (dbt
== VT_FLOAT
&& sbt
== VT_DOUBLE
)
5969 vtop
->c
.f
= (float)vtop
->c
.d
;
5970 else if (dbt
== VT_FLOAT
&& sbt
== VT_LDOUBLE
)
5971 vtop
->c
.f
= (float)vtop
->c
.ld
;
5972 else if (dbt
== VT_DOUBLE
&& sbt
== VT_FLOAT
)
5973 vtop
->c
.d
= (double)vtop
->c
.f
;
5974 else if (dbt
== VT_DOUBLE
&& sbt
== VT_LDOUBLE
)
5975 vtop
->c
.d
= (double)vtop
->c
.ld
;
5976 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_FLOAT
)
5977 vtop
->c
.ld
= (long double)vtop
->c
.f
;
5978 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_DOUBLE
)
5979 vtop
->c
.ld
= (long double)vtop
->c
.d
;
5981 /* non constant case: generate code */
5985 /* convert int to fp */
5988 case VT_LLONG
| VT_UNSIGNED
:
5990 /* XXX: add const cases for long long */
5992 case VT_INT
| VT_UNSIGNED
:
5994 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.ui
; break;
5995 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.ui
; break;
5996 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.ui
; break;
6001 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.i
; break;
6002 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.i
; break;
6003 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.i
; break;
6009 #if !defined(TCC_TARGET_ARM)
6016 /* convert fp to int */
6017 if (dbt
== VT_BOOL
) {
6021 /* we handle char/short/etc... with generic code */
6022 if (dbt
!= (VT_INT
| VT_UNSIGNED
) &&
6023 dbt
!= (VT_LLONG
| VT_UNSIGNED
) &&
6028 case VT_LLONG
| VT_UNSIGNED
:
6030 /* XXX: add const cases for long long */
6032 case VT_INT
| VT_UNSIGNED
:
6034 case VT_FLOAT
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
6035 case VT_DOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
6036 case VT_LDOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
6042 case VT_FLOAT
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
6043 case VT_DOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
6044 case VT_LDOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
6052 if (dbt
== VT_INT
&& (type
->t
& (VT_BTYPE
| VT_UNSIGNED
)) != dbt
) {
6053 /* additional cast for char/short... */
6058 } else if ((dbt
& VT_BTYPE
) == VT_LLONG
) {
6059 if ((sbt
& VT_BTYPE
) != VT_LLONG
) {
6060 /* scalar to long long */
6062 if (sbt
== (VT_INT
| VT_UNSIGNED
))
6063 vtop
->c
.ll
= vtop
->c
.ui
;
6065 vtop
->c
.ll
= vtop
->c
.i
;
6067 /* machine independent conversion */
6069 /* generate high word */
6070 if (sbt
== (VT_INT
| VT_UNSIGNED
)) {
6078 /* patch second register */
6079 vtop
[-1].r2
= vtop
->r
;
6083 } else if (dbt
== VT_BOOL
) {
6084 /* scalar to bool */
6087 } else if ((dbt
& VT_BTYPE
) == VT_BYTE
||
6088 (dbt
& VT_BTYPE
) == VT_SHORT
) {
6089 if (sbt
== VT_PTR
) {
6090 vtop
->type
.t
= VT_INT
;
6091 warning("nonportable conversion from pointer to char/short");
6093 force_charshort_cast(dbt
);
6094 } else if ((dbt
& VT_BTYPE
) == VT_INT
) {
6096 if (sbt
== VT_LLONG
) {
6097 /* from long long: just take low order word */
6101 /* if lvalue and single word type, nothing to do because
6102 the lvalue already contains the real type size (see
6103 VT_LVAL_xxx constants) */
6105 } else if ((dbt
& VT_BTYPE
) == VT_PTR
&& !(vtop
->r
& VT_LVAL
)) {
6106 /* if we are casting between pointer types,
6107 we must update the VT_LVAL_xxx size */
6108 vtop
->r
= (vtop
->r
& ~VT_LVAL_TYPE
)
6109 | (lvalue_type(type
->ref
->type
.t
) & VT_LVAL_TYPE
);
6114 /* return type size. Put alignment at 'a' */
6115 static int type_size(CType
*type
, int *a
)
6120 bt
= type
->t
& VT_BTYPE
;
6121 if (bt
== VT_STRUCT
) {
6126 } else if (bt
== VT_PTR
) {
6127 if (type
->t
& VT_ARRAY
) {
6129 return type_size(&s
->type
, a
) * s
->c
;
6134 } else if (bt
== VT_LDOUBLE
) {
6136 return LDOUBLE_SIZE
;
6137 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
6138 #ifdef TCC_TARGET_I386
6140 #elif defined(TCC_TARGET_ARM)
6150 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
6153 } else if (bt
== VT_SHORT
) {
6157 /* char, void, function, _Bool */
6163 /* return the pointed type of t */
6164 static inline CType
*pointed_type(CType
*type
)
6166 return &type
->ref
->type
;
6169 /* modify type so that its it is a pointer to type. */
6170 static void mk_pointer(CType
*type
)
6173 s
= sym_push(SYM_FIELD
, type
, 0, -1);
6174 type
->t
= VT_PTR
| (type
->t
& ~VT_TYPE
);
6178 /* compare function types. OLD functions match any new functions */
6179 static int is_compatible_func(CType
*type1
, CType
*type2
)
6185 if (!is_compatible_types(&s1
->type
, &s2
->type
))
6187 /* check func_call */
6188 if (FUNC_CALL(s1
->r
) != FUNC_CALL(s2
->r
))
6190 /* XXX: not complete */
6191 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
6195 while (s1
!= NULL
) {
6198 if (!is_compatible_parameter_types(&s1
->type
, &s2
->type
))
6208 /* return true if type1 and type2 are the same. If unqualified is
6209 true, qualifiers on the types are ignored.
6211 - enums are not checked as gcc __builtin_types_compatible_p ()
6213 static int compare_types(CType
*type1
, CType
*type2
, int unqualified
)
6217 t1
= type1
->t
& VT_TYPE
;
6218 t2
= type2
->t
& VT_TYPE
;
6220 /* strip qualifiers before comparing */
6221 t1
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6222 t2
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6224 /* XXX: bitfields ? */
6227 /* test more complicated cases */
6228 bt1
= t1
& VT_BTYPE
;
6229 if (bt1
== VT_PTR
) {
6230 type1
= pointed_type(type1
);
6231 type2
= pointed_type(type2
);
6232 return is_compatible_types(type1
, type2
);
6233 } else if (bt1
== VT_STRUCT
) {
6234 return (type1
->ref
== type2
->ref
);
6235 } else if (bt1
== VT_FUNC
) {
6236 return is_compatible_func(type1
, type2
);
6242 /* return true if type1 and type2 are exactly the same (including
6245 static int is_compatible_types(CType
*type1
, CType
*type2
)
6247 return compare_types(type1
,type2
,0);
6250 /* return true if type1 and type2 are the same (ignoring qualifiers).
6252 static int is_compatible_parameter_types(CType
*type1
, CType
*type2
)
6254 return compare_types(type1
,type2
,1);
6257 /* print a type. If 'varstr' is not NULL, then the variable is also
6258 printed in the type */
6260 /* XXX: add array and function pointers */
6261 void type_to_str(char *buf
, int buf_size
,
6262 CType
*type
, const char *varstr
)
6269 t
= type
->t
& VT_TYPE
;
6272 if (t
& VT_CONSTANT
)
6273 pstrcat(buf
, buf_size
, "const ");
6274 if (t
& VT_VOLATILE
)
6275 pstrcat(buf
, buf_size
, "volatile ");
6276 if (t
& VT_UNSIGNED
)
6277 pstrcat(buf
, buf_size
, "unsigned ");
6307 tstr
= "long double";
6309 pstrcat(buf
, buf_size
, tstr
);
6313 if (bt
== VT_STRUCT
)
6317 pstrcat(buf
, buf_size
, tstr
);
6318 v
= type
->ref
->v
& ~SYM_STRUCT
;
6319 if (v
>= SYM_FIRST_ANOM
)
6320 pstrcat(buf
, buf_size
, "<anonymous>");
6322 pstrcat(buf
, buf_size
, get_tok_str(v
, NULL
));
6326 type_to_str(buf
, buf_size
, &s
->type
, varstr
);
6327 pstrcat(buf
, buf_size
, "(");
6329 while (sa
!= NULL
) {
6330 type_to_str(buf1
, sizeof(buf1
), &sa
->type
, NULL
);
6331 pstrcat(buf
, buf_size
, buf1
);
6334 pstrcat(buf
, buf_size
, ", ");
6336 pstrcat(buf
, buf_size
, ")");
6340 pstrcpy(buf1
, sizeof(buf1
), "*");
6342 pstrcat(buf1
, sizeof(buf1
), varstr
);
6343 type_to_str(buf
, buf_size
, &s
->type
, buf1
);
6347 pstrcat(buf
, buf_size
, " ");
6348 pstrcat(buf
, buf_size
, varstr
);
6353 /* verify type compatibility to store vtop in 'dt' type, and generate
6355 static void gen_assign_cast(CType
*dt
)
6357 CType
*st
, *type1
, *type2
, tmp_type1
, tmp_type2
;
6358 char buf1
[256], buf2
[256];
6361 st
= &vtop
->type
; /* source type */
6362 dbt
= dt
->t
& VT_BTYPE
;
6363 sbt
= st
->t
& VT_BTYPE
;
6364 if (dt
->t
& VT_CONSTANT
)
6365 warning("assignment of read-only location");
6368 /* special cases for pointers */
6369 /* '0' can also be a pointer */
6370 if (is_null_pointer(vtop
))
6372 /* accept implicit pointer to integer cast with warning */
6373 if (is_integer_btype(sbt
)) {
6374 warning("assignment makes pointer from integer without a cast");
6377 type1
= pointed_type(dt
);
6378 /* a function is implicitely a function pointer */
6379 if (sbt
== VT_FUNC
) {
6380 if ((type1
->t
& VT_BTYPE
) != VT_VOID
&&
6381 !is_compatible_types(pointed_type(dt
), st
))
6388 type2
= pointed_type(st
);
6389 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
6390 (type2
->t
& VT_BTYPE
) == VT_VOID
) {
6391 /* void * can match anything */
6393 /* exact type match, except for unsigned */
6396 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6397 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6398 if (!is_compatible_types(&tmp_type1
, &tmp_type2
))
6399 warning("assignment from incompatible pointer type");
6401 /* check const and volatile */
6402 if ((!(type1
->t
& VT_CONSTANT
) && (type2
->t
& VT_CONSTANT
)) ||
6403 (!(type1
->t
& VT_VOLATILE
) && (type2
->t
& VT_VOLATILE
)))
6404 warning("assignment discards qualifiers from pointer target type");
6410 if (sbt
== VT_PTR
|| sbt
== VT_FUNC
) {
6411 warning("assignment makes integer from pointer without a cast");
6413 /* XXX: more tests */
6418 tmp_type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6419 tmp_type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6420 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
6422 type_to_str(buf1
, sizeof(buf1
), st
, NULL
);
6423 type_to_str(buf2
, sizeof(buf2
), dt
, NULL
);
6424 error("cannot cast '%s' to '%s'", buf1
, buf2
);
6432 /* store vtop in lvalue pushed on stack */
6435 int sbt
, dbt
, ft
, r
, t
, size
, align
, bit_size
, bit_pos
, rc
, delayed_cast
;
6437 ft
= vtop
[-1].type
.t
;
6438 sbt
= vtop
->type
.t
& VT_BTYPE
;
6439 dbt
= ft
& VT_BTYPE
;
6440 if (((sbt
== VT_INT
|| sbt
== VT_SHORT
) && dbt
== VT_BYTE
) ||
6441 (sbt
== VT_INT
&& dbt
== VT_SHORT
)) {
6442 /* optimize char/short casts */
6443 delayed_cast
= VT_MUSTCAST
;
6444 vtop
->type
.t
= ft
& VT_TYPE
;
6445 /* XXX: factorize */
6446 if (ft
& VT_CONSTANT
)
6447 warning("assignment of read-only location");
6450 if (!(ft
& VT_BITFIELD
))
6451 gen_assign_cast(&vtop
[-1].type
);
6454 if (sbt
== VT_STRUCT
) {
6455 /* if structure, only generate pointer */
6456 /* structure assignment : generate memcpy */
6457 /* XXX: optimize if small size */
6458 if (!nocode_wanted
) {
6459 size
= type_size(&vtop
->type
, &align
);
6463 vpush_global_sym(&func_old_type
, TOK_memcpy8
);
6464 else if(!(align
& 3))
6465 vpush_global_sym(&func_old_type
, TOK_memcpy4
);
6468 vpush_global_sym(&func_old_type
, TOK_memcpy
);
6472 vtop
->type
.t
= VT_INT
;
6476 vtop
->type
.t
= VT_INT
;
6488 /* leave source on stack */
6489 } else if (ft
& VT_BITFIELD
) {
6490 /* bitfield store handling */
6491 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
6492 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
6493 /* remove bit field info to avoid loops */
6494 vtop
[-1].type
.t
= ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
6496 /* duplicate source into other register */
6501 /* duplicate destination */
6503 vtop
[-1] = vtop
[-2];
6505 /* mask and shift source */
6506 vpushi((1 << bit_size
) - 1);
6510 /* load destination, mask and or with source */
6512 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
6518 /* pop off shifted source from "duplicate source..." above */
6522 #ifdef CONFIG_TCC_BCHECK
6523 /* bound check case */
6524 if (vtop
[-1].r
& VT_MUSTBOUND
) {
6530 if (!nocode_wanted
) {
6534 r
= gv(rc
); /* generate value */
6535 /* if lvalue was saved on stack, must read it */
6536 if ((vtop
[-1].r
& VT_VALMASK
) == VT_LLOCAL
) {
6538 t
= get_reg(RC_INT
);
6540 sv
.r
= VT_LOCAL
| VT_LVAL
;
6541 sv
.c
.ul
= vtop
[-1].c
.ul
;
6543 vtop
[-1].r
= t
| VT_LVAL
;
6546 /* two word case handling : store second register at word + 4 */
6547 if ((ft
& VT_BTYPE
) == VT_LLONG
) {
6549 /* convert to int to increment easily */
6550 vtop
->type
.t
= VT_INT
;
6556 /* XXX: it works because r2 is spilled last ! */
6557 store(vtop
->r2
, vtop
- 1);
6561 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
6562 vtop
->r
|= delayed_cast
;
6566 /* post defines POST/PRE add. c is the token ++ or -- */
6567 void inc(int post
, int c
)
6570 vdup(); /* save lvalue */
6572 gv_dup(); /* duplicate value */
6577 vpushi(c
- TOK_MID
);
6579 vstore(); /* store value */
6581 vpop(); /* if post op, return saved value */
6584 /* Parse GNUC __attribute__ extension. Currently, the following
6585 extensions are recognized:
6586 - aligned(n) : set data/function alignment.
6587 - packed : force data alignment to 1
6588 - section(x) : generate data/code in this section.
6589 - unused : currently ignored, but may be used someday.
6590 - regparm(n) : pass function parameters in registers (i386 only)
6592 static void parse_attribute(AttributeDef
*ad
)
6596 while (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
) {
6600 while (tok
!= ')') {
6601 if (tok
< TOK_IDENT
)
6602 expect("attribute name");
6610 expect("section name");
6611 ad
->section
= find_section(tcc_state
, (char *)tokc
.cstr
->data
);
6620 if (n
<= 0 || (n
& (n
- 1)) != 0)
6621 error("alignment must be a positive power of two");
6634 /* currently, no need to handle it because tcc does not
6635 track unused objects */
6639 /* currently, no need to handle it because tcc does not
6640 track unused objects */
6645 FUNC_CALL(ad
->func_attr
) = FUNC_CDECL
;
6650 FUNC_CALL(ad
->func_attr
) = FUNC_STDCALL
;
6652 #ifdef TCC_TARGET_I386
6662 FUNC_CALL(ad
->func_attr
) = FUNC_FASTCALL1
+ n
- 1;
6668 FUNC_CALL(ad
->func_attr
) = FUNC_FASTCALLW
;
6672 FUNC_EXPORT(ad
->func_attr
) = 1;
6675 if (tcc_state
->warn_unsupported
)
6676 warning("'%s' attribute ignored", get_tok_str(t
, NULL
));
6677 /* skip parameters */
6679 int parenthesis
= 0;
6683 else if (tok
== ')')
6686 } while (parenthesis
&& tok
!= -1);
6699 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6700 static void struct_decl(CType
*type
, int u
)
6702 int a
, v
, size
, align
, maxalign
, c
, offset
;
6703 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
;
6704 Sym
*s
, *ss
, *ass
, **ps
;
6708 a
= tok
; /* save decl type */
6713 /* struct already defined ? return it */
6715 expect("struct/union/enum name");
6719 error("invalid type");
6726 /* we put an undefined size for struct/union */
6727 s
= sym_push(v
| SYM_STRUCT
, &type1
, 0, -1);
6728 s
->r
= 0; /* default alignment is zero as gcc */
6729 /* put struct/union/enum name in type */
6737 error("struct/union/enum already defined");
6738 /* cannot be empty */
6740 /* non empty enums are not allowed */
6741 if (a
== TOK_ENUM
) {
6745 expect("identifier");
6751 /* enum symbols have static storage */
6752 ss
= sym_push(v
, &int_type
, VT_CONST
, c
);
6753 ss
->type
.t
|= VT_STATIC
;
6758 /* NOTE: we accept a trailing comma */
6768 while (tok
!= '}') {
6769 parse_btype(&btype
, &ad
);
6775 type_decl(&type1
, &ad
, &v
, TYPE_DIRECT
| TYPE_ABSTRACT
);
6776 if (v
== 0 && (type1
.t
& VT_BTYPE
) != VT_STRUCT
)
6777 expect("identifier");
6778 if ((type1
.t
& VT_BTYPE
) == VT_FUNC
||
6779 (type1
.t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
| VT_INLINE
)))
6780 error("invalid type for '%s'",
6781 get_tok_str(v
, NULL
));
6785 bit_size
= expr_const();
6786 /* XXX: handle v = 0 case for messages */
6788 error("negative width in bit-field '%s'",
6789 get_tok_str(v
, NULL
));
6790 if (v
&& bit_size
== 0)
6791 error("zero width for bit-field '%s'",
6792 get_tok_str(v
, NULL
));
6794 size
= type_size(&type1
, &align
);
6796 if (align
< ad
.aligned
)
6798 } else if (ad
.packed
) {
6800 } else if (*tcc_state
->pack_stack_ptr
) {
6801 if (align
> *tcc_state
->pack_stack_ptr
)
6802 align
= *tcc_state
->pack_stack_ptr
;
6805 if (bit_size
>= 0) {
6806 bt
= type1
.t
& VT_BTYPE
;
6812 error("bitfields must have scalar type");
6814 if (bit_size
> bsize
) {
6815 error("width of '%s' exceeds its type",
6816 get_tok_str(v
, NULL
));
6817 } else if (bit_size
== bsize
) {
6818 /* no need for bit fields */
6820 } else if (bit_size
== 0) {
6821 /* XXX: what to do if only padding in a
6823 /* zero size: means to pad */
6827 /* we do not have enough room ? */
6828 if ((bit_pos
+ bit_size
) > bsize
)
6831 /* XXX: handle LSB first */
6832 type1
.t
|= VT_BITFIELD
|
6833 (bit_pos
<< VT_STRUCT_SHIFT
) |
6834 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
6835 bit_pos
+= bit_size
;
6840 if (v
!= 0 || (type1
.t
& VT_BTYPE
) == VT_STRUCT
) {
6841 /* add new memory data only if starting
6843 if (lbit_pos
== 0) {
6844 if (a
== TOK_STRUCT
) {
6845 c
= (c
+ align
- 1) & -align
;
6854 if (align
> maxalign
)
6858 printf("add field %s offset=%d",
6859 get_tok_str(v
, NULL
), offset
);
6860 if (type1
.t
& VT_BITFIELD
) {
6861 printf(" pos=%d size=%d",
6862 (type1
.t
>> VT_STRUCT_SHIFT
) & 0x3f,
6863 (type1
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
6868 if (v
== 0 && (type1
.t
& VT_BTYPE
) == VT_STRUCT
) {
6870 while ((ass
= ass
->next
) != NULL
) {
6871 ss
= sym_push(ass
->v
, &ass
->type
, 0, offset
+ ass
->c
);
6876 ss
= sym_push(v
| SYM_FIELD
, &type1
, 0, offset
);
6880 if (tok
== ';' || tok
== TOK_EOF
)
6887 /* store size and alignment */
6888 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
6894 /* return 0 if no type declaration. otherwise, return the basic type
6897 static int parse_btype(CType
*type
, AttributeDef
*ad
)
6899 int t
, u
, type_found
, typespec_found
, typedef_found
;
6903 memset(ad
, 0, sizeof(AttributeDef
));
6911 /* currently, we really ignore extension */
6921 if ((t
& VT_BTYPE
) != 0)
6922 error("too many basic types");
6938 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
6939 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6940 } else if ((t
& VT_BTYPE
) == VT_LONG
) {
6941 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
6955 if ((t
& VT_BTYPE
) == VT_LONG
) {
6956 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6963 struct_decl(&type1
, VT_ENUM
);
6966 type
->ref
= type1
.ref
;
6970 struct_decl(&type1
, VT_STRUCT
);
6973 /* type modifiers */
7026 /* GNUC attribute */
7027 case TOK_ATTRIBUTE1
:
7028 case TOK_ATTRIBUTE2
:
7029 parse_attribute(ad
);
7036 parse_expr_type(&type1
);
7039 if (typespec_found
|| typedef_found
)
7042 if (!s
|| !(s
->type
.t
& VT_TYPEDEF
))
7045 t
|= (s
->type
.t
& ~VT_TYPEDEF
);
7046 type
->ref
= s
->type
.ref
;
7054 if ((t
& (VT_SIGNED
|VT_UNSIGNED
)) == (VT_SIGNED
|VT_UNSIGNED
))
7055 error("signed and unsigned modifier");
7056 if (tcc_state
->char_is_unsigned
) {
7057 if ((t
& (VT_SIGNED
|VT_UNSIGNED
|VT_BTYPE
)) == VT_BYTE
)
7062 /* long is never used as type */
7063 if ((t
& VT_BTYPE
) == VT_LONG
)
7064 t
= (t
& ~VT_BTYPE
) | VT_INT
;
7069 /* convert a function parameter type (array to pointer and function to
7070 function pointer) */
7071 static inline void convert_parameter_type(CType
*pt
)
7073 /* remove const and volatile qualifiers (XXX: const could be used
7074 to indicate a const function parameter */
7075 pt
->t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7076 /* array must be transformed to pointer according to ANSI C */
7078 if ((pt
->t
& VT_BTYPE
) == VT_FUNC
) {
7083 static void post_type(CType
*type
, AttributeDef
*ad
)
7085 int n
, l
, t1
, arg_size
, align
;
7086 Sym
**plast
, *s
, *first
;
7091 /* function declaration */
7099 /* read param name and compute offset */
7100 if (l
!= FUNC_OLD
) {
7101 if (!parse_btype(&pt
, &ad1
)) {
7103 error("invalid type");
7110 if ((pt
.t
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
7112 type_decl(&pt
, &ad1
, &n
, TYPE_DIRECT
| TYPE_ABSTRACT
);
7113 if ((pt
.t
& VT_BTYPE
) == VT_VOID
)
7114 error("parameter declared as void");
7115 arg_size
+= (type_size(&pt
, &align
) + 3) & ~3;
7120 expect("identifier");
7124 convert_parameter_type(&pt
);
7125 s
= sym_push(n
| SYM_FIELD
, &pt
, 0, 0);
7131 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
7138 /* if no parameters, then old type prototype */
7142 t1
= type
->t
& VT_STORAGE
;
7143 /* NOTE: const is ignored in returned type as it has a special
7144 meaning in gcc / C++ */
7145 type
->t
&= ~(VT_STORAGE
| VT_CONSTANT
);
7146 post_type(type
, ad
);
7147 /* we push a anonymous symbol which will contain the function prototype */
7148 FUNC_ARGS(ad
->func_attr
) = arg_size
;
7149 s
= sym_push(SYM_FIELD
, type
, ad
->func_attr
, l
);
7151 type
->t
= t1
| VT_FUNC
;
7153 } else if (tok
== '[') {
7154 /* array definition */
7160 error("invalid array size");
7163 /* parse next post type */
7164 t1
= type
->t
& VT_STORAGE
;
7165 type
->t
&= ~VT_STORAGE
;
7166 post_type(type
, ad
);
7168 /* we push a anonymous symbol which will contain the array
7170 s
= sym_push(SYM_FIELD
, type
, 0, n
);
7171 type
->t
= t1
| VT_ARRAY
| VT_PTR
;
7176 /* Parse a type declaration (except basic type), and return the type
7177 in 'type'. 'td' is a bitmask indicating which kind of type decl is
7178 expected. 'type' should contain the basic type. 'ad' is the
7179 attribute definition of the basic type. It can be modified by
7182 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
)
7185 CType type1
, *type2
;
7188 while (tok
== '*') {
7196 qualifiers
|= VT_CONSTANT
;
7201 qualifiers
|= VT_VOLATILE
;
7209 type
->t
|= qualifiers
;
7212 /* XXX: clarify attribute handling */
7213 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7214 parse_attribute(ad
);
7216 /* recursive type */
7217 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7218 type1
.t
= 0; /* XXX: same as int */
7221 /* XXX: this is not correct to modify 'ad' at this point, but
7222 the syntax is not clear */
7223 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7224 parse_attribute(ad
);
7225 type_decl(&type1
, ad
, v
, td
);
7228 /* type identifier */
7229 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
7233 if (!(td
& TYPE_ABSTRACT
))
7234 expect("identifier");
7238 post_type(type
, ad
);
7239 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
7240 parse_attribute(ad
);
7243 /* append type at the end of type1 */
7256 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7257 static int lvalue_type(int t
)
7262 if (bt
== VT_BYTE
|| bt
== VT_BOOL
)
7264 else if (bt
== VT_SHORT
)
7268 if (t
& VT_UNSIGNED
)
7269 r
|= VT_LVAL_UNSIGNED
;
7273 /* indirection with full error checking and bound check */
7274 static void indir(void)
7276 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
) {
7277 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FUNC
)
7281 if ((vtop
->r
& VT_LVAL
) && !nocode_wanted
)
7283 vtop
->type
= *pointed_type(&vtop
->type
);
7284 /* Arrays and functions are never lvalues */
7285 if (!(vtop
->type
.t
& VT_ARRAY
)
7286 && (vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
) {
7287 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7288 /* if bound checking, the referenced pointer must be checked */
7289 if (do_bounds_check
)
7290 vtop
->r
|= VT_MUSTBOUND
;
7294 /* pass a parameter to a function and do type checking and casting */
7295 static void gfunc_param_typed(Sym
*func
, Sym
*arg
)
7300 func_type
= func
->c
;
7301 if (func_type
== FUNC_OLD
||
7302 (func_type
== FUNC_ELLIPSIS
&& arg
== NULL
)) {
7303 /* default casting : only need to convert float to double */
7304 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FLOAT
) {
7308 } else if (arg
== NULL
) {
7309 error("too many arguments to function");
7312 type
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
7313 gen_assign_cast(&type
);
7317 /* parse an expression of the form '(type)' or '(expr)' and return its
7319 static void parse_expr_type(CType
*type
)
7325 if (parse_btype(type
, &ad
)) {
7326 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7333 static void parse_type(CType
*type
)
7338 if (!parse_btype(type
, &ad
)) {
7341 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7344 static void vpush_tokc(int t
)
7348 vsetc(&type
, VT_CONST
, &tokc
);
7351 static void unary(void)
7353 int n
, t
, align
, size
, r
;
7358 /* XXX: GCC 2.95.3 does not generate a table although it should be
7372 vpush_tokc(VT_INT
| VT_UNSIGNED
);
7376 vpush_tokc(VT_LLONG
);
7380 vpush_tokc(VT_LLONG
| VT_UNSIGNED
);
7384 vpush_tokc(VT_FLOAT
);
7388 vpush_tokc(VT_DOUBLE
);
7392 vpush_tokc(VT_LDOUBLE
);
7395 case TOK___FUNCTION__
:
7397 goto tok_identifier
;
7403 /* special function name identifier */
7404 len
= strlen(funcname
) + 1;
7405 /* generate char[len] type */
7410 vpush_ref(&type
, data_section
, data_section
->data_offset
, len
);
7411 ptr
= section_ptr_add(data_section
, len
);
7412 memcpy(ptr
, funcname
, len
);
7417 #ifdef TCC_TARGET_PE
7418 t
= VT_SHORT
| VT_UNSIGNED
;
7424 /* string parsing */
7427 if (tcc_state
->warn_write_strings
)
7432 memset(&ad
, 0, sizeof(AttributeDef
));
7433 decl_initializer_alloc(&type
, &ad
, VT_CONST
, 2, 0, 0);
7438 if (parse_btype(&type
, &ad
)) {
7439 type_decl(&type
, &ad
, &n
, TYPE_ABSTRACT
);
7441 /* check ISOC99 compound literal */
7443 /* data is allocated locally by default */
7448 /* all except arrays are lvalues */
7449 if (!(type
.t
& VT_ARRAY
))
7450 r
|= lvalue_type(type
.t
);
7451 memset(&ad
, 0, sizeof(AttributeDef
));
7452 decl_initializer_alloc(&type
, &ad
, r
, 1, 0, 0);
7457 } else if (tok
== '{') {
7458 /* save all registers */
7460 /* statement expression : we do not accept break/continue
7461 inside as GCC does */
7462 block(NULL
, NULL
, NULL
, NULL
, 0, 1);
7477 /* functions names must be treated as function pointers,
7478 except for unary '&' and sizeof. Since we consider that
7479 functions are not lvalues, we only have to handle it
7480 there and in function calls. */
7481 /* arrays can also be used although they are not lvalues */
7482 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
&&
7483 !(vtop
->type
.t
& VT_ARRAY
) && !(vtop
->type
.t
& VT_LLOCAL
))
7485 mk_pointer(&vtop
->type
);
7491 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
)
7492 vtop
->c
.i
= !vtop
->c
.i
;
7493 else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
7494 vtop
->c
.i
= vtop
->c
.i
^ 1;
7497 vseti(VT_JMP
, gtst(1, 0));
7508 /* in order to force cast, we add zero */
7510 if ((vtop
->type
.t
& VT_BTYPE
) == VT_PTR
)
7511 error("pointer not accepted for unary plus");
7521 parse_expr_type(&type
);
7525 size
= type_size(&type
, &align
);
7526 if (t
== TOK_SIZEOF
) {
7528 error("sizeof applied to an incomplete type");
7533 vtop
->type
.t
|= VT_UNSIGNED
;
7536 case TOK_builtin_types_compatible_p
:
7545 type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7546 type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7547 vpushi(is_compatible_types(&type1
, &type2
));
7550 case TOK_builtin_constant_p
:
7552 int saved_nocode_wanted
, res
;
7555 saved_nocode_wanted
= nocode_wanted
;
7558 res
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
7560 nocode_wanted
= saved_nocode_wanted
;
7580 goto tok_identifier
;
7582 /* allow to take the address of a label */
7583 if (tok
< TOK_UIDENT
)
7584 expect("label identifier");
7585 s
= label_find(tok
);
7587 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
7589 if (s
->r
== LABEL_DECLARED
)
7590 s
->r
= LABEL_FORWARD
;
7593 s
->type
.t
= VT_VOID
;
7594 mk_pointer(&s
->type
);
7595 s
->type
.t
|= VT_STATIC
;
7597 vset(&s
->type
, VT_CONST
| VT_SYM
, 0);
7606 expect("identifier");
7610 error("'%s' undeclared", get_tok_str(t
, NULL
));
7611 /* for simple function calls, we tolerate undeclared
7612 external reference to int() function */
7613 if (tcc_state
->warn_implicit_function_declaration
)
7614 warning("implicit declaration of function '%s'",
7615 get_tok_str(t
, NULL
));
7616 s
= external_global_sym(t
, &func_old_type
, 0);
7618 if ((s
->type
.t
& (VT_STATIC
| VT_INLINE
| VT_BTYPE
)) ==
7619 (VT_STATIC
| VT_INLINE
| VT_FUNC
)) {
7620 /* if referencing an inline function, then we generate a
7621 symbol to it if not already done. It will have the
7622 effect to generate code for it at the end of the
7623 compilation unit. Inline function as always
7624 generated in the text section. */
7626 put_extern_sym(s
, text_section
, 0, 0);
7627 r
= VT_SYM
| VT_CONST
;
7631 vset(&s
->type
, r
, s
->c
);
7632 /* if forward reference, we must point to s */
7633 if (vtop
->r
& VT_SYM
) {
7640 /* post operations */
7642 if (tok
== TOK_INC
|| tok
== TOK_DEC
) {
7645 } else if (tok
== '.' || tok
== TOK_ARROW
) {
7647 if (tok
== TOK_ARROW
)
7652 /* expect pointer on structure */
7653 if ((vtop
->type
.t
& VT_BTYPE
) != VT_STRUCT
)
7654 expect("struct or union");
7658 while ((s
= s
->next
) != NULL
) {
7663 error("field not found: %s", get_tok_str(tok
& ~SYM_FIELD
, NULL
));
7664 /* add field offset to pointer */
7665 vtop
->type
= char_pointer_type
; /* change type to 'char *' */
7668 /* change type to field type, and set to lvalue */
7669 vtop
->type
= s
->type
;
7670 /* an array is never an lvalue */
7671 if (!(vtop
->type
.t
& VT_ARRAY
)) {
7672 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7673 /* if bound checking, the referenced pointer must be checked */
7674 if (do_bounds_check
)
7675 vtop
->r
|= VT_MUSTBOUND
;
7678 } else if (tok
== '[') {
7684 } else if (tok
== '(') {
7690 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
) {
7691 /* pointer test (no array accepted) */
7692 if ((vtop
->type
.t
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
7693 vtop
->type
= *pointed_type(&vtop
->type
);
7694 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
)
7698 expect("function pointer");
7701 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
7703 /* get return type */
7706 sa
= s
->next
; /* first parameter */
7709 /* compute first implicit argument if a structure is returned */
7710 if ((s
->type
.t
& VT_BTYPE
) == VT_STRUCT
) {
7711 /* get some space for the returned structure */
7712 size
= type_size(&s
->type
, &align
);
7713 loc
= (loc
- size
) & -align
;
7715 ret
.r
= VT_LOCAL
| VT_LVAL
;
7716 /* pass it as 'int' to avoid structure arg passing
7718 vseti(VT_LOCAL
, loc
);
7723 /* return in register */
7724 if (is_float(ret
.type
.t
)) {
7727 if ((ret
.type
.t
& VT_BTYPE
) == VT_LLONG
)
7736 gfunc_param_typed(s
, sa
);
7746 error("too few arguments to function");
7748 if (!nocode_wanted
) {
7749 gfunc_call(nb_args
);
7751 vtop
-= (nb_args
+ 1);
7754 vsetc(&ret
.type
, ret
.r
, &ret
.c
);
7762 static void uneq(void)
7768 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
7769 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
7770 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
7785 static void expr_prod(void)
7790 while (tok
== '*' || tok
== '/' || tok
== '%') {
7798 static void expr_sum(void)
7803 while (tok
== '+' || tok
== '-') {
7811 static void expr_shift(void)
7816 while (tok
== TOK_SHL
|| tok
== TOK_SAR
) {
7824 static void expr_cmp(void)
7829 while ((tok
>= TOK_ULE
&& tok
<= TOK_GT
) ||
7830 tok
== TOK_ULT
|| tok
== TOK_UGE
) {
7838 static void expr_cmpeq(void)
7843 while (tok
== TOK_EQ
|| tok
== TOK_NE
) {
7851 static void expr_and(void)
7854 while (tok
== '&') {
7861 static void expr_xor(void)
7864 while (tok
== '^') {
7871 static void expr_or(void)
7874 while (tok
== '|') {
7881 /* XXX: fix this mess */
7882 static void expr_land_const(void)
7885 while (tok
== TOK_LAND
) {
7892 /* XXX: fix this mess */
7893 static void expr_lor_const(void)
7896 while (tok
== TOK_LOR
) {
7903 /* only used if non constant */
7904 static void expr_land(void)
7909 if (tok
== TOK_LAND
) {
7914 if (tok
!= TOK_LAND
) {
7924 static void expr_lor(void)
7929 if (tok
== TOK_LOR
) {
7934 if (tok
!= TOK_LOR
) {
7944 /* XXX: better constant handling */
7945 static void expr_eq(void)
7947 int tt
, u
, r1
, r2
, rc
, t1
, t2
, bt1
, bt2
;
7949 CType type
, type1
, type2
;
7958 if (tok
== ':' && gnu_ext
) {
7974 if (vtop
!= vstack
) {
7975 /* needed to avoid having different registers saved in
7977 if (is_float(vtop
->type
.t
))
7984 if (tok
== ':' && gnu_ext
) {
7992 sv
= *vtop
; /* save value to handle it later */
7993 vtop
--; /* no vpop so that FP stack is not flushed */
8001 bt1
= t1
& VT_BTYPE
;
8003 bt2
= t2
& VT_BTYPE
;
8004 /* cast operands to correct type according to ISOC rules */
8005 if (is_float(bt1
) || is_float(bt2
)) {
8006 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
8007 type
.t
= VT_LDOUBLE
;
8008 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
8013 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
8014 /* cast to biggest op */
8016 /* convert to unsigned if it does not fit in a long long */
8017 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
8018 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
8019 type
.t
|= VT_UNSIGNED
;
8020 } else if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
8021 /* XXX: test pointer compatibility */
8023 } else if (bt1
== VT_FUNC
|| bt2
== VT_FUNC
) {
8024 /* XXX: test function pointer compatibility */
8026 } else if (bt1
== VT_STRUCT
|| bt2
== VT_STRUCT
) {
8027 /* XXX: test structure compatibility */
8029 } else if (bt1
== VT_VOID
|| bt2
== VT_VOID
) {
8030 /* NOTE: as an extension, we accept void on only one side */
8033 /* integer operations */
8035 /* convert to unsigned if it does not fit in an integer */
8036 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
8037 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
8038 type
.t
|= VT_UNSIGNED
;
8041 /* now we convert second operand */
8043 if (VT_STRUCT
== (vtop
->type
.t
& VT_BTYPE
))
8046 if (is_float(type
.t
)) {
8048 } else if ((type
.t
& VT_BTYPE
) == VT_LLONG
) {
8049 /* for long longs, we use fixed registers to avoid having
8050 to handle a complicated move */
8055 /* this is horrible, but we must also convert first
8059 /* put again first value and cast it */
8062 if (VT_STRUCT
== (vtop
->type
.t
& VT_BTYPE
))
8072 static void gexpr(void)
8083 /* parse an expression and return its type without any side effect. */
8084 static void expr_type(CType
*type
)
8086 int saved_nocode_wanted
;
8088 saved_nocode_wanted
= nocode_wanted
;
8093 nocode_wanted
= saved_nocode_wanted
;
8096 /* parse a unary expression and return its type without any side
8098 static void unary_type(CType
*type
)
8110 /* parse a constant expression and return value in vtop. */
8111 static void expr_const1(void)
8120 /* parse an integer constant and return its value. */
8121 static int expr_const(void)
8125 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
8126 expect("constant expression");
8132 /* return the label token if current token is a label, otherwise
8134 static int is_label(void)
8138 /* fast test first */
8139 if (tok
< TOK_UIDENT
)
8141 /* no need to save tokc because tok is an identifier */
8148 unget_tok(last_tok
);
8153 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
8154 int case_reg
, int is_expr
)
8159 /* generate line number info */
8161 (last_line_num
!= file
->line_num
|| last_ind
!= ind
)) {
8162 put_stabn(N_SLINE
, 0, file
->line_num
, ind
- func_ind
);
8164 last_line_num
= file
->line_num
;
8168 /* default return value is (void) */
8170 vtop
->type
.t
= VT_VOID
;
8173 if (tok
== TOK_IF
) {
8180 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
8182 if (c
== TOK_ELSE
) {
8186 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
8187 gsym(d
); /* patch else jmp */
8190 } else if (tok
== TOK_WHILE
) {
8198 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8202 } else if (tok
== '{') {
8206 /* record local declaration stack position */
8208 llabel
= local_label_stack
;
8209 /* handle local labels declarations */
8210 if (tok
== TOK_LABEL
) {
8213 if (tok
< TOK_UIDENT
)
8214 expect("label identifier");
8215 label_push(&local_label_stack
, tok
, LABEL_DECLARED
);
8225 while (tok
!= '}') {
8230 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
8233 /* pop locally defined labels */
8234 label_pop(&local_label_stack
, llabel
);
8235 /* pop locally defined symbols */
8236 sym_pop(&local_stack
, s
);
8238 } else if (tok
== TOK_RETURN
) {
8242 gen_assign_cast(&func_vt
);
8243 if ((func_vt
.t
& VT_BTYPE
) == VT_STRUCT
) {
8245 /* if returning structure, must copy it to implicit
8246 first pointer arg location */
8249 size
= type_size(&func_vt
,&align
);
8252 if((vtop
->r
!= (VT_LOCAL
| VT_LVAL
) || (vtop
->c
.i
& 3))
8256 loc
= (loc
- size
) & -4;
8259 vset(&type
, VT_LOCAL
| VT_LVAL
, addr
);
8262 vset(&int_type
, VT_LOCAL
| VT_LVAL
, addr
);
8264 vtop
->type
= int_type
;
8270 vset(&type
, VT_LOCAL
| VT_LVAL
, func_vc
);
8273 /* copy structure value to pointer */
8278 } else if (is_float(func_vt
.t
)) {
8283 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
8286 rsym
= gjmp(rsym
); /* jmp */
8287 } else if (tok
== TOK_BREAK
) {
8290 error("cannot break");
8291 *bsym
= gjmp(*bsym
);
8294 } else if (tok
== TOK_CONTINUE
) {
8297 error("cannot continue");
8298 *csym
= gjmp(*csym
);
8301 } else if (tok
== TOK_FOR
) {
8328 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8333 if (tok
== TOK_DO
) {
8338 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8349 if (tok
== TOK_SWITCH
) {
8353 /* XXX: other types than integer */
8354 case_reg
= gv(RC_INT
);
8358 b
= gjmp(0); /* jump to first case */
8360 block(&a
, csym
, &b
, &c
, case_reg
, 0);
8361 /* if no default, jmp after switch */
8369 if (tok
== TOK_CASE
) {
8376 if (gnu_ext
&& tok
== TOK_DOTS
) {
8380 warning("empty case range");
8382 /* since a case is like a label, we must skip it with a jmp */
8389 *case_sym
= gtst(1, 0);
8392 *case_sym
= gtst(1, 0);
8396 *case_sym
= gtst(1, *case_sym
);
8401 goto block_after_label
;
8403 if (tok
== TOK_DEFAULT
) {
8409 error("too many 'default'");
8412 goto block_after_label
;
8414 if (tok
== TOK_GOTO
) {
8416 if (tok
== '*' && gnu_ext
) {
8420 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
8423 } else if (tok
>= TOK_UIDENT
) {
8424 s
= label_find(tok
);
8425 /* put forward definition if needed */
8427 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
8429 if (s
->r
== LABEL_DECLARED
)
8430 s
->r
= LABEL_FORWARD
;
8432 /* label already defined */
8433 if (s
->r
& LABEL_FORWARD
)
8434 s
->next
= (void *)gjmp((long)s
->next
);
8436 gjmp_addr((long)s
->next
);
8439 expect("label identifier");
8442 } else if (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
) {
8450 if (s
->r
== LABEL_DEFINED
)
8451 error("duplicate label '%s'", get_tok_str(s
->v
, NULL
));
8452 gsym((long)s
->next
);
8453 s
->r
= LABEL_DEFINED
;
8455 s
= label_push(&global_label_stack
, b
, LABEL_DEFINED
);
8457 s
->next
= (void *)ind
;
8458 /* we accept this, but it is a mistake */
8461 warning("deprecated use of label at end of compound statement");
8465 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
8468 /* expression case */
8483 /* t is the array or struct type. c is the array or struct
8484 address. cur_index/cur_field is the pointer to the current
8485 value. 'size_only' is true if only size info is needed (only used
8487 static void decl_designator(CType
*type
, Section
*sec
, unsigned long c
,
8488 int *cur_index
, Sym
**cur_field
,
8492 int notfirst
, index
, index_last
, align
, l
, nb_elems
, elem_size
;
8498 if (gnu_ext
&& (l
= is_label()) != 0)
8500 while (tok
== '[' || tok
== '.') {
8502 if (!(type
->t
& VT_ARRAY
))
8503 expect("array type");
8506 index
= expr_const();
8507 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
8508 expect("invalid index");
8509 if (tok
== TOK_DOTS
&& gnu_ext
) {
8511 index_last
= expr_const();
8512 if (index_last
< 0 ||
8513 (s
->c
>= 0 && index_last
>= s
->c
) ||
8515 expect("invalid index");
8521 *cur_index
= index_last
;
8522 type
= pointed_type(type
);
8523 elem_size
= type_size(type
, &align
);
8524 c
+= index
* elem_size
;
8525 /* NOTE: we only support ranges for last designator */
8526 nb_elems
= index_last
- index
+ 1;
8527 if (nb_elems
!= 1) {
8536 if ((type
->t
& VT_BTYPE
) != VT_STRUCT
)
8537 expect("struct/union type");
8550 /* XXX: fix this mess by using explicit storage field */
8552 type1
.t
|= (type
->t
& ~VT_TYPE
);
8566 if (type
->t
& VT_ARRAY
) {
8568 type
= pointed_type(type
);
8569 c
+= index
* type_size(type
, &align
);
8573 error("too many field init");
8574 /* XXX: fix this mess by using explicit storage field */
8576 type1
.t
|= (type
->t
& ~VT_TYPE
);
8581 decl_initializer(type
, sec
, c
, 0, size_only
);
8583 /* XXX: make it more general */
8584 if (!size_only
&& nb_elems
> 1) {
8585 unsigned long c_end
;
8590 error("range init not supported yet for dynamic storage");
8591 c_end
= c
+ nb_elems
* elem_size
;
8592 if (c_end
> sec
->data_allocated
)
8593 section_realloc(sec
, c_end
);
8594 src
= sec
->data
+ c
;
8596 for(i
= 1; i
< nb_elems
; i
++) {
8598 memcpy(dst
, src
, elem_size
);
8604 #define EXPR_CONST 1
8607 /* store a value or an expression directly in global data or in local array */
8608 static void init_putv(CType
*type
, Section
*sec
, unsigned long c
,
8609 int v
, int expr_type
)
8611 int saved_global_expr
, bt
, bit_pos
, bit_size
;
8613 unsigned long long bit_mask
;
8621 /* compound literals must be allocated globally in this case */
8622 saved_global_expr
= global_expr
;
8625 global_expr
= saved_global_expr
;
8626 /* NOTE: symbols are accepted */
8627 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) != VT_CONST
)
8628 error("initializer element is not constant");
8636 dtype
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
8639 /* XXX: not portable */
8640 /* XXX: generate error if incorrect relocation */
8641 gen_assign_cast(&dtype
);
8642 bt
= type
->t
& VT_BTYPE
;
8643 ptr
= sec
->data
+ c
;
8644 /* XXX: make code faster ? */
8645 if (!(type
->t
& VT_BITFIELD
)) {
8650 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
8651 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
8652 bit_mask
= (1LL << bit_size
) - 1;
8654 if ((vtop
->r
& VT_SYM
) &&
8660 (bt
== VT_INT
&& bit_size
!= 32)))
8661 error("initializer element is not computable at load time");
8664 *(char *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8667 *(short *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8670 *(double *)ptr
= vtop
->c
.d
;
8673 *(long double *)ptr
= vtop
->c
.ld
;
8676 *(long long *)ptr
|= (vtop
->c
.ll
& bit_mask
) << bit_pos
;
8679 if (vtop
->r
& VT_SYM
) {
8680 greloc(sec
, vtop
->sym
, c
, R_DATA_32
);
8682 *(int *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8687 vset(&dtype
, VT_LOCAL
|VT_LVAL
, c
);
8694 /* put zeros for variable based init */
8695 static void init_putz(CType
*t
, Section
*sec
, unsigned long c
, int size
)
8698 /* nothing to do because globals are already set to zero */
8700 vpush_global_sym(&func_old_type
, TOK_memset
);
8708 /* 't' contains the type and storage info. 'c' is the offset of the
8709 object in section 'sec'. If 'sec' is NULL, it means stack based
8710 allocation. 'first' is true if array '{' must be read (multi
8711 dimension implicit array init handling). 'size_only' is true if
8712 size only evaluation is wanted (only for arrays). */
8713 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
8714 int first
, int size_only
)
8716 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
8717 int size1
, align1
, expr_type
;
8721 if (type
->t
& VT_ARRAY
) {
8725 t1
= pointed_type(type
);
8726 size1
= type_size(t1
, &align1
);
8729 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
8735 /* only parse strings here if correct type (otherwise: handle
8736 them as ((w)char *) expressions */
8737 if ((tok
== TOK_LSTR
&&
8738 #ifdef TCC_TARGET_PE
8739 (t1
->t
& VT_BTYPE
) == VT_SHORT
&& (t1
->t
& VT_UNSIGNED
)
8741 (t1
->t
& VT_BTYPE
) == VT_INT
8743 ) || (tok
== TOK_STR
&& (t1
->t
& VT_BTYPE
) == VT_BYTE
)) {
8744 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8749 /* compute maximum number of chars wanted */
8751 cstr_len
= cstr
->size
;
8753 cstr_len
= cstr
->size
/ sizeof(nwchar_t
);
8756 if (n
>= 0 && nb
> (n
- array_length
))
8757 nb
= n
- array_length
;
8760 warning("initializer-string for array is too long");
8761 /* in order to go faster for common case (char
8762 string in global variable, we handle it
8764 if (sec
&& tok
== TOK_STR
&& size1
== 1) {
8765 memcpy(sec
->data
+ c
+ array_length
, cstr
->data
, nb
);
8769 ch
= ((unsigned char *)cstr
->data
)[i
];
8771 ch
= ((nwchar_t
*)cstr
->data
)[i
];
8772 init_putv(t1
, sec
, c
+ (array_length
+ i
) * size1
,
8780 /* only add trailing zero if enough storage (no
8781 warning in this case since it is standard) */
8782 if (n
< 0 || array_length
< n
) {
8784 init_putv(t1
, sec
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
8790 while (tok
!= '}') {
8791 decl_designator(type
, sec
, c
, &index
, NULL
, size_only
);
8792 if (n
>= 0 && index
>= n
)
8793 error("index too large");
8794 /* must put zero in holes (note that doing it that way
8795 ensures that it even works with designators) */
8796 if (!size_only
&& array_length
< index
) {
8797 init_putz(t1
, sec
, c
+ array_length
* size1
,
8798 (index
- array_length
) * size1
);
8801 if (index
> array_length
)
8802 array_length
= index
;
8803 /* special test for multi dimensional arrays (may not
8804 be strictly correct if designators are used at the
8806 if (index
>= n
&& no_oblock
)
8815 /* put zeros at the end */
8816 if (!size_only
&& n
>= 0 && array_length
< n
) {
8817 init_putz(t1
, sec
, c
+ array_length
* size1
,
8818 (n
- array_length
) * size1
);
8820 /* patch type size if needed */
8822 s
->c
= array_length
;
8823 } else if ((type
->t
& VT_BTYPE
) == VT_STRUCT
&&
8824 (sec
|| !first
|| tok
== '{')) {
8827 /* NOTE: the previous test is a specific case for automatic
8828 struct/union init */
8829 /* XXX: union needs only one init */
8831 /* XXX: this test is incorrect for local initializers
8832 beginning with ( without {. It would be much more difficult
8833 to do it correctly (ideally, the expression parser should
8834 be used in all cases) */
8840 while (tok
== '(') {
8844 if (!parse_btype(&type1
, &ad1
))
8846 type_decl(&type1
, &ad1
, &n
, TYPE_ABSTRACT
);
8848 if (!is_assignable_types(type
, &type1
))
8849 error("invalid type for cast");
8854 if (first
|| tok
== '{') {
8863 while (tok
!= '}') {
8864 decl_designator(type
, sec
, c
, NULL
, &f
, size_only
);
8866 if (!size_only
&& array_length
< index
) {
8867 init_putz(type
, sec
, c
+ array_length
,
8868 index
- array_length
);
8870 index
= index
+ type_size(&f
->type
, &align1
);
8871 if (index
> array_length
)
8872 array_length
= index
;
8874 if (no_oblock
&& f
== NULL
)
8880 /* put zeros at the end */
8881 if (!size_only
&& array_length
< n
) {
8882 init_putz(type
, sec
, c
+ array_length
,
8891 } else if (tok
== '{') {
8893 decl_initializer(type
, sec
, c
, first
, size_only
);
8895 } else if (size_only
) {
8896 /* just skip expression */
8898 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
8902 else if (tok
== ')')
8907 /* currently, we always use constant expression for globals
8908 (may change for scripting case) */
8909 expr_type
= EXPR_CONST
;
8911 expr_type
= EXPR_ANY
;
8912 init_putv(type
, sec
, c
, 0, expr_type
);
8916 /* parse an initializer for type 't' if 'has_init' is non zero, and
8917 allocate space in local or global data space ('r' is either
8918 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8919 variable 'v' of scope 'scope' is declared before initializers are
8920 parsed. If 'v' is zero, then a reference to the new object is put
8921 in the value stack. If 'has_init' is 2, a special parsing is done
8922 to handle string constants. */
8923 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
8924 int has_init
, int v
, int scope
)
8926 int size
, align
, addr
, data_offset
;
8928 ParseState saved_parse_state
;
8929 TokenString init_str
;
8932 size
= type_size(type
, &align
);
8933 /* If unknown size, we must evaluate it before
8934 evaluating initializers because
8935 initializers can generate global data too
8936 (e.g. string pointers or ISOC99 compound
8937 literals). It also simplifies local
8938 initializers handling */
8939 tok_str_new(&init_str
);
8942 error("unknown type size");
8943 /* get all init string */
8944 if (has_init
== 2) {
8945 /* only get strings */
8946 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8947 tok_str_add_tok(&init_str
);
8952 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
8954 error("unexpected end of file in initializer");
8955 tok_str_add_tok(&init_str
);
8958 else if (tok
== '}') {
8966 tok_str_add(&init_str
, -1);
8967 tok_str_add(&init_str
, 0);
8970 save_parse_state(&saved_parse_state
);
8972 macro_ptr
= init_str
.str
;
8974 decl_initializer(type
, NULL
, 0, 1, 1);
8975 /* prepare second initializer parsing */
8976 macro_ptr
= init_str
.str
;
8979 /* if still unknown size, error */
8980 size
= type_size(type
, &align
);
8982 error("unknown type size");
8984 /* take into account specified alignment if bigger */
8986 if (ad
->aligned
> align
)
8987 align
= ad
->aligned
;
8988 } else if (ad
->packed
) {
8991 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
8993 if (do_bounds_check
&& (type
->t
& VT_ARRAY
))
8995 loc
= (loc
- size
) & -align
;
8997 /* handles bounds */
8998 /* XXX: currently, since we do only one pass, we cannot track
8999 '&' operators, so we add only arrays */
9000 if (do_bounds_check
&& (type
->t
& VT_ARRAY
)) {
9001 unsigned long *bounds_ptr
;
9002 /* add padding between regions */
9004 /* then add local bound info */
9005 bounds_ptr
= section_ptr_add(lbounds_section
, 2 * sizeof(unsigned long));
9006 bounds_ptr
[0] = addr
;
9007 bounds_ptr
[1] = size
;
9010 /* local variable */
9011 sym_push(v
, type
, r
, addr
);
9013 /* push local reference */
9014 vset(type
, r
, addr
);
9020 if (v
&& scope
== VT_CONST
) {
9021 /* see if the symbol was already defined */
9024 if (!is_compatible_types(&sym
->type
, type
))
9025 error("incompatible types for redefinition of '%s'",
9026 get_tok_str(v
, NULL
));
9027 if (sym
->type
.t
& VT_EXTERN
) {
9028 /* if the variable is extern, it was not allocated */
9029 sym
->type
.t
&= ~VT_EXTERN
;
9030 /* set array size if it was ommited in extern
9032 if ((sym
->type
.t
& VT_ARRAY
) &&
9033 sym
->type
.ref
->c
< 0 &&
9035 sym
->type
.ref
->c
= type
->ref
->c
;
9037 /* we accept several definitions of the same
9038 global variable. this is tricky, because we
9039 must play with the SHN_COMMON type of the symbol */
9040 /* XXX: should check if the variable was already
9041 initialized. It is incorrect to initialized it
9043 /* no init data, we won't add more to the symbol */
9050 /* allocate symbol in corresponding section */
9055 else if (tcc_state
->nocommon
)
9059 data_offset
= sec
->data_offset
;
9060 data_offset
= (data_offset
+ align
- 1) & -align
;
9062 /* very important to increment global pointer at this time
9063 because initializers themselves can create new initializers */
9064 data_offset
+= size
;
9065 /* add padding if bound check */
9066 if (do_bounds_check
)
9068 sec
->data_offset
= data_offset
;
9069 /* allocate section space to put the data */
9070 if (sec
->sh_type
!= SHT_NOBITS
&&
9071 data_offset
> sec
->data_allocated
)
9072 section_realloc(sec
, data_offset
);
9073 /* align section if needed */
9074 if (align
> sec
->sh_addralign
)
9075 sec
->sh_addralign
= align
;
9077 addr
= 0; /* avoid warning */
9081 if (scope
!= VT_CONST
|| !sym
) {
9082 sym
= sym_push(v
, type
, r
| VT_SYM
, 0);
9084 /* update symbol definition */
9086 put_extern_sym(sym
, sec
, addr
, size
);
9089 /* put a common area */
9090 put_extern_sym(sym
, NULL
, align
, size
);
9091 /* XXX: find a nicer way */
9092 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
9093 esym
->st_shndx
= SHN_COMMON
;
9098 /* push global reference */
9099 sym
= get_sym_ref(type
, sec
, addr
, size
);
9101 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
9105 /* handles bounds now because the symbol must be defined
9106 before for the relocation */
9107 if (do_bounds_check
) {
9108 unsigned long *bounds_ptr
;
9110 greloc(bounds_section
, sym
, bounds_section
->data_offset
, R_DATA_32
);
9111 /* then add global bound info */
9112 bounds_ptr
= section_ptr_add(bounds_section
, 2 * sizeof(long));
9113 bounds_ptr
[0] = 0; /* relocated */
9114 bounds_ptr
[1] = size
;
9118 decl_initializer(type
, sec
, addr
, 1, 0);
9119 /* restore parse state if needed */
9121 tok_str_free(init_str
.str
);
9122 restore_parse_state(&saved_parse_state
);
9128 void put_func_debug(Sym
*sym
)
9133 /* XXX: we put here a dummy type */
9134 snprintf(buf
, sizeof(buf
), "%s:%c1",
9135 funcname
, sym
->type
.t
& VT_STATIC
? 'f' : 'F');
9136 put_stabs_r(buf
, N_FUN
, 0, file
->line_num
, 0,
9137 cur_text_section
, sym
->c
);
9142 /* parse an old style function declaration list */
9143 /* XXX: check multiple parameter */
9144 static void func_decl_list(Sym
*func_sym
)
9151 /* parse each declaration */
9152 while (tok
!= '{' && tok
!= ';' && tok
!= ',' && tok
!= TOK_EOF
) {
9153 if (!parse_btype(&btype
, &ad
))
9154 expect("declaration list");
9155 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
9156 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
9158 /* we accept no variable after */
9162 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
9163 /* find parameter in function parameter list */
9166 if ((s
->v
& ~SYM_FIELD
) == v
)
9170 error("declaration for parameter '%s' but no such parameter",
9171 get_tok_str(v
, NULL
));
9173 /* check that no storage specifier except 'register' was given */
9174 if (type
.t
& VT_STORAGE
)
9175 error("storage class specified for '%s'", get_tok_str(v
, NULL
));
9176 convert_parameter_type(&type
);
9177 /* we can add the type (NOTE: it could be local to the function) */
9179 /* accept other parameters */
9190 /* parse a function defined by symbol 'sym' and generate its code in
9191 'cur_text_section' */
9192 static void gen_function(Sym
*sym
)
9194 int saved_nocode_wanted
= nocode_wanted
;
9196 ind
= cur_text_section
->data_offset
;
9197 /* NOTE: we patch the symbol size later */
9198 put_extern_sym(sym
, cur_text_section
, ind
, 0);
9199 funcname
= get_tok_str(sym
->v
, NULL
);
9201 /* put debug symbol */
9203 put_func_debug(sym
);
9204 /* push a dummy symbol to enable local sym storage */
9205 sym_push2(&local_stack
, SYM_FIELD
, 0, 0);
9206 gfunc_prolog(&sym
->type
);
9208 block(NULL
, NULL
, NULL
, NULL
, 0, 0);
9211 cur_text_section
->data_offset
= ind
;
9212 label_pop(&global_label_stack
, NULL
);
9213 sym_pop(&local_stack
, NULL
); /* reset local stack */
9214 /* end of function */
9215 /* patch symbol size */
9216 ((Elf32_Sym
*)symtab_section
->data
)[sym
->c
].st_size
=
9219 put_stabn(N_FUN
, 0, 0, ind
- func_ind
);
9221 funcname
= ""; /* for safety */
9222 func_vt
.t
= VT_VOID
; /* for safety */
9223 ind
= 0; /* for safety */
9224 nocode_wanted
= saved_nocode_wanted
;
9227 static void gen_inline_functions(void)
9231 int *str
, inline_generated
;
9233 /* iterate while inline function are referenced */
9235 inline_generated
= 0;
9236 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
9238 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
9239 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
9240 (VT_STATIC
| VT_INLINE
) &&
9242 /* the function was used: generate its code and
9243 convert it to a normal function */
9244 str
= INLINE_DEF(sym
->r
);
9245 sym
->r
= VT_SYM
| VT_CONST
;
9246 sym
->type
.t
&= ~VT_INLINE
;
9250 cur_text_section
= text_section
;
9252 macro_ptr
= NULL
; /* fail safe */
9255 inline_generated
= 1;
9258 if (!inline_generated
)
9262 /* free all remaining inline function tokens */
9263 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
9265 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
9266 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
9267 (VT_STATIC
| VT_INLINE
)) {
9268 //gr printf("sym %d %s\n", sym->r, get_tok_str(sym->v, NULL));
9269 if (sym
->r
== (VT_SYM
| VT_CONST
)) //gr beware!
9271 str
= INLINE_DEF(sym
->r
);
9273 sym
->r
= 0; /* fail safe */
9278 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
9279 static void decl(int l
)
9287 if (!parse_btype(&btype
, &ad
)) {
9288 /* skip redundant ';' */
9289 /* XXX: find more elegant solution */
9294 if (l
== VT_CONST
&&
9295 (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
)) {
9296 /* global asm block */
9300 /* special test for old K&R protos without explicit int
9301 type. Only accepted when defining global data */
9302 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
9306 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
9307 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
9309 /* we accept no variable after */
9313 while (1) { /* iterate thru each declaration */
9315 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
9319 type_to_str(buf
, sizeof(buf
), t
, get_tok_str(v
, NULL
));
9320 printf("type = '%s'\n", buf
);
9323 if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9324 /* if old style function prototype, we accept a
9327 if (sym
->c
== FUNC_OLD
)
9328 func_decl_list(sym
);
9333 error("cannot use local functions");
9334 if ((type
.t
& VT_BTYPE
) != VT_FUNC
)
9335 expect("function definition");
9337 /* reject abstract declarators in function definition */
9339 while ((sym
= sym
->next
) != NULL
)
9340 if (!(sym
->v
& ~SYM_FIELD
))
9341 expect("identifier");
9343 /* XXX: cannot do better now: convert extern line to static inline */
9344 if ((type
.t
& (VT_EXTERN
| VT_INLINE
)) == (VT_EXTERN
| VT_INLINE
))
9345 type
.t
= (type
.t
& ~VT_EXTERN
) | VT_STATIC
;
9349 if ((sym
->type
.t
& VT_BTYPE
) != VT_FUNC
)
9351 /* specific case: if not func_call defined, we put
9352 the one of the prototype */
9353 /* XXX: should have default value */
9354 r
= sym
->type
.ref
->r
;
9355 if (FUNC_CALL(r
) != FUNC_CDECL
9356 && FUNC_CALL(type
.ref
->r
) == FUNC_CDECL
)
9357 FUNC_CALL(type
.ref
->r
) = FUNC_CALL(r
);
9359 FUNC_EXPORT(type
.ref
->r
) = 1;
9361 if (!is_compatible_types(&sym
->type
, &type
)) {
9363 error("incompatible types for redefinition of '%s'",
9364 get_tok_str(v
, NULL
));
9366 /* if symbol is already defined, then put complete type */
9369 /* put function symbol */
9370 sym
= global_identifier_push(v
, type
.t
, 0);
9371 sym
->type
.ref
= type
.ref
;
9374 /* static inline functions are just recorded as a kind
9375 of macro. Their code will be emitted at the end of
9376 the compilation unit only if they are used */
9377 if ((type
.t
& (VT_INLINE
| VT_STATIC
)) ==
9378 (VT_INLINE
| VT_STATIC
)) {
9379 TokenString func_str
;
9382 tok_str_new(&func_str
);
9388 error("unexpected end of file");
9389 tok_str_add_tok(&func_str
);
9394 } else if (t
== '}') {
9396 if (block_level
== 0)
9400 tok_str_add(&func_str
, -1);
9401 tok_str_add(&func_str
, 0);
9402 INLINE_DEF(sym
->r
) = func_str
.str
;
9404 /* compute text section */
9405 cur_text_section
= ad
.section
;
9406 if (!cur_text_section
)
9407 cur_text_section
= text_section
;
9408 sym
->r
= VT_SYM
| VT_CONST
;
9413 if (btype
.t
& VT_TYPEDEF
) {
9414 /* save typedefed type */
9415 /* XXX: test storage specifiers ? */
9416 sym
= sym_push(v
, &type
, 0, 0);
9417 sym
->type
.t
|= VT_TYPEDEF
;
9418 } else if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9419 /* external function definition */
9420 /* specific case for func_call attribute */
9422 type
.ref
->r
= ad
.func_attr
;
9423 external_sym(v
, &type
, 0);
9425 /* not lvalue if array */
9427 if (!(type
.t
& VT_ARRAY
))
9428 r
|= lvalue_type(type
.t
);
9429 has_init
= (tok
== '=');
9430 if ((btype
.t
& VT_EXTERN
) ||
9431 ((type
.t
& VT_ARRAY
) && (type
.t
& VT_STATIC
) &&
9432 !has_init
&& l
== VT_CONST
&& type
.ref
->c
< 0)) {
9433 /* external variable */
9434 /* NOTE: as GCC, uninitialized global static
9435 arrays of null size are considered as
9437 external_sym(v
, &type
, r
);
9439 type
.t
|= (btype
.t
& VT_STATIC
); /* Retain "static". */
9440 if (type
.t
& VT_STATIC
)
9446 decl_initializer_alloc(&type
, &ad
, r
,
9460 /* better than nothing, but needs extension to handle '-E' option
9462 static void preprocess_init(TCCState
*s1
)
9464 s1
->include_stack_ptr
= s1
->include_stack
;
9465 /* XXX: move that before to avoid having to initialize
9466 file->ifdef_stack_ptr ? */
9467 s1
->ifdef_stack_ptr
= s1
->ifdef_stack
;
9468 file
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
9470 /* XXX: not ANSI compliant: bound checking says error */
9472 s1
->pack_stack
[0] = 0;
9473 s1
->pack_stack_ptr
= s1
->pack_stack
;
9476 /* compile the C file opened in 'file'. Return non zero if errors. */
9477 static int tcc_compile(TCCState
*s1
)
9481 volatile int section_sym
;
9484 printf("%s: **** new file\n", file
->filename
);
9486 preprocess_init(s1
);
9489 anon_sym
= SYM_FIRST_ANOM
;
9491 /* file info: full path + filename */
9492 section_sym
= 0; /* avoid warning */
9494 section_sym
= put_elf_sym(symtab_section
, 0, 0,
9495 ELF32_ST_INFO(STB_LOCAL
, STT_SECTION
), 0,
9496 text_section
->sh_num
, NULL
);
9497 getcwd(buf
, sizeof(buf
));
9499 normalize_slashes(buf
);
9501 pstrcat(buf
, sizeof(buf
), "/");
9502 put_stabs_r(buf
, N_SO
, 0, 0,
9503 text_section
->data_offset
, text_section
, section_sym
);
9504 put_stabs_r(file
->filename
, N_SO
, 0, 0,
9505 text_section
->data_offset
, text_section
, section_sym
);
9507 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9508 symbols can be safely used */
9509 put_elf_sym(symtab_section
, 0, 0,
9510 ELF32_ST_INFO(STB_LOCAL
, STT_FILE
), 0,
9511 SHN_ABS
, file
->filename
);
9513 /* define some often used types */
9514 int_type
.t
= VT_INT
;
9516 char_pointer_type
.t
= VT_BYTE
;
9517 mk_pointer(&char_pointer_type
);
9519 func_old_type
.t
= VT_FUNC
;
9520 func_old_type
.ref
= sym_push(SYM_FIELD
, &int_type
, FUNC_CDECL
, FUNC_OLD
);
9522 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
9523 float_type
.t
= VT_FLOAT
;
9524 double_type
.t
= VT_DOUBLE
;
9526 func_float_type
.t
= VT_FUNC
;
9527 func_float_type
.ref
= sym_push(SYM_FIELD
, &float_type
, FUNC_CDECL
, FUNC_OLD
);
9528 func_double_type
.t
= VT_FUNC
;
9529 func_double_type
.ref
= sym_push(SYM_FIELD
, &double_type
, FUNC_CDECL
, FUNC_OLD
);
9533 /* define 'void *alloca(unsigned int)' builtin function */
9538 sym
= sym_push(p
, mk_pointer(VT_VOID
), FUNC_CDECL
, FUNC_NEW
);
9539 s1
= sym_push(SYM_FIELD
, VT_UNSIGNED
| VT_INT
, 0, 0);
9542 sym_push(TOK_alloca
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), VT_CONST
, 0);
9546 define_start
= define_stack
;
9549 if (setjmp(s1
->error_jmp_buf
) == 0) {
9551 s1
->error_set_jmp_enabled
= 1;
9553 ch
= file
->buf_ptr
[0];
9554 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
9555 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
;
9559 expect("declaration");
9561 /* end of translation unit info */
9563 put_stabs_r(NULL
, N_SO
, 0, 0,
9564 text_section
->data_offset
, text_section
, section_sym
);
9567 s1
->error_set_jmp_enabled
= 0;
9569 /* reset define stack, but leave -Dsymbols (may be incorrect if
9570 they are undefined) */
9571 free_defines(define_start
);
9573 gen_inline_functions();
9575 sym_pop(&global_stack
, NULL
);
9577 return s1
->nb_errors
!= 0 ? -1 : 0;
9580 /* Preprocess the current file */
9581 /* XXX: add line and file infos, add options to preserve spaces */
9582 static int tcc_preprocess(TCCState
*s1
)
9587 preprocess_init(s1
);
9589 define_start
= define_stack
;
9591 ch
= file
->buf_ptr
[0];
9592 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
9593 parse_flags
= PARSE_FLAG_ASM_COMMENTS
| PARSE_FLAG_PREPROCESS
|
9594 PARSE_FLAG_LINEFEED
;
9598 if (tok
== TOK_EOF
) {
9600 } else if (tok
== TOK_LINEFEED
) {
9604 fputc(' ', s1
->outfile
);
9607 fputs(get_tok_str(tok
, &tokc
), s1
->outfile
);
9610 free_defines(define_start
);
9615 int tcc_compile_string(TCCState
*s
, const char *str
)
9617 BufferedFile bf1
, *bf
= &bf1
;
9621 /* init file structure */
9623 /* XXX: avoid copying */
9625 buf
= tcc_malloc(len
+ 1);
9628 memcpy(buf
, str
, len
);
9631 bf
->buf_end
= buf
+ len
;
9632 pstrcpy(bf
->filename
, sizeof(bf
->filename
), "<string>");
9636 ret
= tcc_compile(s
);
9640 /* currently, no need to close */
9645 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9646 void tcc_define_symbol(TCCState
*s1
, const char *sym
, const char *value
)
9648 BufferedFile bf1
, *bf
= &bf1
;
9650 pstrcpy(bf
->buffer
, IO_BUF_SIZE
, sym
);
9651 pstrcat(bf
->buffer
, IO_BUF_SIZE
, " ");
9655 pstrcat(bf
->buffer
, IO_BUF_SIZE
, value
);
9657 /* init file structure */
9659 bf
->buf_ptr
= bf
->buffer
;
9660 bf
->buf_end
= bf
->buffer
+ strlen(bf
->buffer
);
9661 *bf
->buf_end
= CH_EOB
;
9662 bf
->filename
[0] = '\0';
9666 s1
->include_stack_ptr
= s1
->include_stack
;
9668 /* parse with define parser */
9669 ch
= file
->buf_ptr
[0];
9675 /* undefine a preprocessor symbol */
9676 void tcc_undefine_symbol(TCCState
*s1
, const char *sym
)
9680 ts
= tok_alloc(sym
, strlen(sym
));
9681 s
= define_find(ts
->tok
);
9682 /* undefine symbol by putting an invalid name */
9687 #ifdef CONFIG_TCC_ASM
9689 #ifdef TCC_TARGET_I386
9690 #include "i386-asm.c"
9695 static void asm_instr(void)
9697 error("inline asm() not supported");
9699 static void asm_global_instr(void)
9701 error("inline asm() not supported");
9707 #ifdef TCC_TARGET_COFF
9708 #include "tcccoff.c"
9711 #ifdef TCC_TARGET_PE
9715 /* print the position in the source file of PC value 'pc' by reading
9716 the stabs debug information */
9717 static void rt_printline(unsigned long wanted_pc
)
9719 Stab_Sym
*sym
, *sym_end
;
9720 char func_name
[128], last_func_name
[128];
9721 unsigned long func_addr
, last_pc
, pc
;
9722 const char *incl_files
[INCLUDE_STACK_SIZE
];
9723 int incl_index
, len
, last_line_num
, i
;
9724 const char *str
, *p
;
9726 fprintf(stderr
, "0x%08lx:", wanted_pc
);
9728 func_name
[0] = '\0';
9731 last_func_name
[0] = '\0';
9732 last_pc
= 0xffffffff;
9734 sym
= (Stab_Sym
*)stab_section
->data
+ 1;
9735 sym_end
= (Stab_Sym
*)(stab_section
->data
+ stab_section
->data_offset
);
9736 while (sym
< sym_end
) {
9737 switch(sym
->n_type
) {
9738 /* function start or end */
9740 if (sym
->n_strx
== 0) {
9741 /* we test if between last line and end of function */
9742 pc
= sym
->n_value
+ func_addr
;
9743 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
9745 func_name
[0] = '\0';
9748 str
= stabstr_section
->data
+ sym
->n_strx
;
9749 p
= strchr(str
, ':');
9751 pstrcpy(func_name
, sizeof(func_name
), str
);
9754 if (len
> sizeof(func_name
) - 1)
9755 len
= sizeof(func_name
) - 1;
9756 memcpy(func_name
, str
, len
);
9757 func_name
[len
] = '\0';
9759 func_addr
= sym
->n_value
;
9762 /* line number info */
9764 pc
= sym
->n_value
+ func_addr
;
9765 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
9768 last_line_num
= sym
->n_desc
;
9770 strcpy(last_func_name
, func_name
);
9774 str
= stabstr_section
->data
+ sym
->n_strx
;
9776 if (incl_index
< INCLUDE_STACK_SIZE
) {
9777 incl_files
[incl_index
++] = str
;
9785 if (sym
->n_strx
== 0) {
9786 incl_index
= 0; /* end of translation unit */
9788 str
= stabstr_section
->data
+ sym
->n_strx
;
9789 /* do not add path */
9791 if (len
> 0 && str
[len
- 1] != '/')
9799 /* second pass: we try symtab symbols (no line number info) */
9802 Elf32_Sym
*sym
, *sym_end
;
9805 sym_end
= (Elf32_Sym
*)(symtab_section
->data
+ symtab_section
->data_offset
);
9806 for(sym
= (Elf32_Sym
*)symtab_section
->data
+ 1;
9809 type
= ELF32_ST_TYPE(sym
->st_info
);
9810 if (type
== STT_FUNC
) {
9811 if (wanted_pc
>= sym
->st_value
&&
9812 wanted_pc
< sym
->st_value
+ sym
->st_size
) {
9813 pstrcpy(last_func_name
, sizeof(last_func_name
),
9814 strtab_section
->data
+ sym
->st_name
);
9820 /* did not find any info: */
9821 fprintf(stderr
, " ???\n");
9824 if (last_func_name
[0] != '\0') {
9825 fprintf(stderr
, " %s()", last_func_name
);
9827 if (incl_index
> 0) {
9828 fprintf(stderr
, " (%s:%d",
9829 incl_files
[incl_index
- 1], last_line_num
);
9830 for(i
= incl_index
- 2; i
>= 0; i
--)
9831 fprintf(stderr
, ", included from %s", incl_files
[i
]);
9832 fprintf(stderr
, ")");
9834 fprintf(stderr
, "\n");
9837 #if !defined(_WIN32) && !defined(CONFIG_TCCBOOT)
9841 /* fix for glibc 2.1 */
9847 /* return the PC at frame level 'level'. Return non zero if not found */
9848 static int rt_get_caller_pc(unsigned long *paddr
,
9849 ucontext_t
*uc
, int level
)
9855 #if defined(__FreeBSD__)
9856 *paddr
= uc
->uc_mcontext
.mc_eip
;
9857 #elif defined(__dietlibc__)
9858 *paddr
= uc
->uc_mcontext
.eip
;
9860 *paddr
= uc
->uc_mcontext
.gregs
[REG_EIP
];
9864 #if defined(__FreeBSD__)
9865 fp
= uc
->uc_mcontext
.mc_ebp
;
9866 #elif defined(__dietlibc__)
9867 fp
= uc
->uc_mcontext
.ebp
;
9869 fp
= uc
->uc_mcontext
.gregs
[REG_EBP
];
9871 for(i
=1;i
<level
;i
++) {
9872 /* XXX: check address validity with program info */
9873 if (fp
<= 0x1000 || fp
>= 0xc0000000)
9875 fp
= ((unsigned long *)fp
)[0];
9877 *paddr
= ((unsigned long *)fp
)[1];
9883 #warning add arch specific rt_get_caller_pc()
9885 static int rt_get_caller_pc(unsigned long *paddr
,
9886 ucontext_t
*uc
, int level
)
9892 /* emit a run time error at position 'pc' */
9893 void rt_error(ucontext_t
*uc
, const char *fmt
, ...)
9900 fprintf(stderr
, "Runtime error: ");
9901 vfprintf(stderr
, fmt
, ap
);
9902 fprintf(stderr
, "\n");
9903 for(i
=0;i
<num_callers
;i
++) {
9904 if (rt_get_caller_pc(&pc
, uc
, i
) < 0)
9907 fprintf(stderr
, "at ");
9909 fprintf(stderr
, "by ");
9916 /* signal handler for fatal errors */
9917 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
9919 ucontext_t
*uc
= puc
;
9923 switch(siginf
->si_code
) {
9926 rt_error(uc
, "division by zero");
9929 rt_error(uc
, "floating point exception");
9935 if (rt_bound_error_msg
&& *rt_bound_error_msg
)
9936 rt_error(uc
, *rt_bound_error_msg
);
9938 rt_error(uc
, "dereferencing invalid pointer");
9941 rt_error(uc
, "illegal instruction");
9944 rt_error(uc
, "abort() called");
9947 rt_error(uc
, "caught signal %d", signum
);
9954 /* do all relocations (needed before using tcc_get_symbol()) */
9955 int tcc_relocate(TCCState
*s1
)
9962 #ifdef TCC_TARGET_PE
9965 tcc_add_runtime(s1
);
9968 relocate_common_syms();
9970 tcc_add_linker_symbols(s1
);
9971 #ifndef TCC_TARGET_PE
9972 build_got_entries(s1
);
9974 /* compute relocation address : section are relocated in place. We
9975 also alloc the bss space */
9976 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9977 s
= s1
->sections
[i
];
9978 if (s
->sh_flags
& SHF_ALLOC
) {
9979 if (s
->sh_type
== SHT_NOBITS
)
9980 s
->data
= tcc_mallocz(s
->data_offset
);
9981 s
->sh_addr
= (unsigned long)s
->data
;
9985 relocate_syms(s1
, 1);
9987 if (s1
->nb_errors
!= 0)
9990 /* relocate each section */
9991 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9992 s
= s1
->sections
[i
];
9994 relocate_section(s1
, s
);
9997 /* mark executable sections as executable in memory */
9998 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9999 s
= s1
->sections
[i
];
10000 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_EXECINSTR
)) ==
10001 (SHF_ALLOC
| SHF_EXECINSTR
))
10002 set_pages_executable(s
->data
, s
->data_offset
);
10007 /* launch the compiled program with the given arguments */
10008 int tcc_run(TCCState
*s1
, int argc
, char **argv
)
10010 int (*prog_main
)(int, char **);
10012 if (tcc_relocate(s1
) < 0)
10015 prog_main
= tcc_get_symbol_err(s1
, "main");
10018 #if defined(_WIN32) || defined(CONFIG_TCCBOOT)
10019 error("debug mode currently not available for Windows");
10021 struct sigaction sigact
;
10022 /* install TCC signal handlers to print debug info on fatal
10024 sigact
.sa_flags
= SA_SIGINFO
| SA_RESETHAND
;
10025 sigact
.sa_sigaction
= sig_error
;
10026 sigemptyset(&sigact
.sa_mask
);
10027 sigaction(SIGFPE
, &sigact
, NULL
);
10028 sigaction(SIGILL
, &sigact
, NULL
);
10029 sigaction(SIGSEGV
, &sigact
, NULL
);
10030 sigaction(SIGBUS
, &sigact
, NULL
);
10031 sigaction(SIGABRT
, &sigact
, NULL
);
10035 #ifdef CONFIG_TCC_BCHECK
10036 if (do_bounds_check
) {
10037 void (*bound_init
)(void);
10039 /* set error function */
10040 rt_bound_error_msg
= (void *)tcc_get_symbol_err(s1
,
10041 "__bound_error_msg");
10043 /* XXX: use .init section so that it also work in binary ? */
10044 bound_init
= (void *)tcc_get_symbol_err(s1
, "__bound_init");
10048 return (*prog_main
)(argc
, argv
);
10051 TCCState
*tcc_new(void)
10058 s
= tcc_mallocz(sizeof(TCCState
));
10062 s
->output_type
= TCC_OUTPUT_MEMORY
;
10064 /* init isid table */
10066 isidnum_table
[i
] = isid(i
) || isnum(i
);
10068 /* add all tokens */
10069 table_ident
= NULL
;
10070 memset(hash_ident
, 0, TOK_HASH_SIZE
* sizeof(TokenSym
*));
10072 tok_ident
= TOK_IDENT
;
10081 ts
= tok_alloc(p
, r
- p
- 1);
10085 /* we add dummy defines for some special macros to speed up tests
10086 and to have working defined() */
10087 define_push(TOK___LINE__
, MACRO_OBJ
, NULL
, NULL
);
10088 define_push(TOK___FILE__
, MACRO_OBJ
, NULL
, NULL
);
10089 define_push(TOK___DATE__
, MACRO_OBJ
, NULL
, NULL
);
10090 define_push(TOK___TIME__
, MACRO_OBJ
, NULL
, NULL
);
10092 /* standard defines */
10093 tcc_define_symbol(s
, "__STDC__", NULL
);
10094 tcc_define_symbol(s
, "__STDC_VERSION__", "199901L");
10095 #if defined(TCC_TARGET_I386)
10096 tcc_define_symbol(s
, "__i386__", NULL
);
10098 #if defined(TCC_TARGET_ARM)
10099 tcc_define_symbol(s
, "__ARM_ARCH_4__", NULL
);
10100 tcc_define_symbol(s
, "__arm_elf__", NULL
);
10101 tcc_define_symbol(s
, "__arm_elf", NULL
);
10102 tcc_define_symbol(s
, "arm_elf", NULL
);
10103 tcc_define_symbol(s
, "__arm__", NULL
);
10104 tcc_define_symbol(s
, "__arm", NULL
);
10105 tcc_define_symbol(s
, "arm", NULL
);
10106 tcc_define_symbol(s
, "__APCS_32__", NULL
);
10108 #ifdef TCC_TARGET_PE
10109 tcc_define_symbol(s
, "_WIN32", NULL
);
10111 tcc_define_symbol(s
, "__unix__", NULL
);
10112 tcc_define_symbol(s
, "__unix", NULL
);
10113 #if defined(__linux)
10114 tcc_define_symbol(s
, "__linux__", NULL
);
10115 tcc_define_symbol(s
, "__linux", NULL
);
10118 /* tiny C specific defines */
10119 tcc_define_symbol(s
, "__TINYC__", NULL
);
10121 /* tiny C & gcc defines */
10122 tcc_define_symbol(s
, "__SIZE_TYPE__", "unsigned int");
10123 tcc_define_symbol(s
, "__PTRDIFF_TYPE__", "int");
10124 #ifdef TCC_TARGET_PE
10125 tcc_define_symbol(s
, "__WCHAR_TYPE__", "unsigned short");
10127 tcc_define_symbol(s
, "__WCHAR_TYPE__", "int");
10130 #ifndef TCC_TARGET_PE
10131 /* default library paths */
10132 tcc_add_library_path(s
, "/usr/local/lib");
10133 tcc_add_library_path(s
, "/usr/lib");
10134 tcc_add_library_path(s
, "/lib");
10137 /* no section zero */
10138 dynarray_add((void ***)&s
->sections
, &s
->nb_sections
, NULL
);
10140 /* create standard sections */
10141 text_section
= new_section(s
, ".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
10142 data_section
= new_section(s
, ".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
10143 bss_section
= new_section(s
, ".bss", SHT_NOBITS
, SHF_ALLOC
| SHF_WRITE
);
10145 /* symbols are always generated for linking stage */
10146 symtab_section
= new_symtab(s
, ".symtab", SHT_SYMTAB
, 0,
10148 ".hashtab", SHF_PRIVATE
);
10149 strtab_section
= symtab_section
->link
;
10151 /* private symbol table for dynamic symbols */
10152 s
->dynsymtab_section
= new_symtab(s
, ".dynsymtab", SHT_SYMTAB
, SHF_PRIVATE
,
10154 ".dynhashtab", SHF_PRIVATE
);
10155 s
->alacarte_link
= 1;
10157 #ifdef CHAR_IS_UNSIGNED
10158 s
->char_is_unsigned
= 1;
10160 #if defined(TCC_TARGET_PE) && 0
10161 /* XXX: currently the PE linker is not ready to support that */
10162 s
->leading_underscore
= 1;
10167 void tcc_delete(TCCState
*s1
)
10171 /* free -D defines */
10172 free_defines(NULL
);
10175 n
= tok_ident
- TOK_IDENT
;
10176 for(i
= 0; i
< n
; i
++)
10177 tcc_free(table_ident
[i
]);
10178 tcc_free(table_ident
);
10180 /* free all sections */
10182 free_section(symtab_section
->hash
);
10184 free_section(s1
->dynsymtab_section
->hash
);
10185 free_section(s1
->dynsymtab_section
->link
);
10186 free_section(s1
->dynsymtab_section
);
10188 for(i
= 1; i
< s1
->nb_sections
; i
++)
10189 free_section(s1
->sections
[i
]);
10190 tcc_free(s1
->sections
);
10192 /* free loaded dlls array */
10193 dynarray_reset(&s1
->loaded_dlls
, &s1
->nb_loaded_dlls
);
10195 /* free library paths */
10196 dynarray_reset(&s1
->library_paths
, &s1
->nb_library_paths
);
10198 /* free include paths */
10199 dynarray_reset(&s1
->cached_includes
, &s1
->nb_cached_includes
);
10200 dynarray_reset(&s1
->include_paths
, &s1
->nb_include_paths
);
10201 dynarray_reset(&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
);
10206 int tcc_add_include_path(TCCState
*s1
, const char *pathname
)
10210 pathname1
= tcc_strdup(pathname
);
10211 dynarray_add((void ***)&s1
->include_paths
, &s1
->nb_include_paths
, pathname1
);
10215 int tcc_add_sysinclude_path(TCCState
*s1
, const char *pathname
)
10219 pathname1
= tcc_strdup(pathname
);
10220 dynarray_add((void ***)&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
, pathname1
);
10224 static int tcc_add_file_internal(TCCState
*s1
, const char *filename
, int flags
)
10229 BufferedFile
*saved_file
;
10231 /* find source file type with extension */
10232 ext
= tcc_fileextension(filename
);
10236 /* open the file */
10238 file
= tcc_open(s1
, filename
);
10240 if (flags
& AFF_PRINT_ERROR
) {
10241 error_noabort("file '%s' not found", filename
);
10247 if (flags
& AFF_PREPROCESS
) {
10248 ret
= tcc_preprocess(s1
);
10249 } else if (!ext
[0] || !strcmp(ext
, "c")) {
10250 /* C file assumed */
10251 ret
= tcc_compile(s1
);
10253 #ifdef CONFIG_TCC_ASM
10254 if (!strcmp(ext
, "S")) {
10255 /* preprocessed assembler */
10256 ret
= tcc_assemble(s1
, 1);
10257 } else if (!strcmp(ext
, "s")) {
10258 /* non preprocessed assembler */
10259 ret
= tcc_assemble(s1
, 0);
10262 #ifdef TCC_TARGET_PE
10263 if (!strcmp(ext
, "def")) {
10264 ret
= pe_load_def_file(s1
, file
->fd
);
10269 /* assume executable format: auto guess file type */
10270 ret
= read(fd
, &ehdr
, sizeof(ehdr
));
10271 lseek(fd
, 0, SEEK_SET
);
10273 error_noabort("could not read header");
10275 } else if (ret
!= sizeof(ehdr
)) {
10276 goto try_load_script
;
10279 if (ehdr
.e_ident
[0] == ELFMAG0
&&
10280 ehdr
.e_ident
[1] == ELFMAG1
&&
10281 ehdr
.e_ident
[2] == ELFMAG2
&&
10282 ehdr
.e_ident
[3] == ELFMAG3
) {
10283 file
->line_num
= 0; /* do not display line number if error */
10284 if (ehdr
.e_type
== ET_REL
) {
10285 ret
= tcc_load_object_file(s1
, fd
, 0);
10286 } else if (ehdr
.e_type
== ET_DYN
) {
10287 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
10288 #ifdef TCC_TARGET_PE
10292 h
= dlopen(filename
, RTLD_GLOBAL
| RTLD_LAZY
);
10299 ret
= tcc_load_dll(s1
, fd
, filename
,
10300 (flags
& AFF_REFERENCED_DLL
) != 0);
10303 error_noabort("unrecognized ELF file");
10306 } else if (memcmp((char *)&ehdr
, ARMAG
, 8) == 0) {
10307 file
->line_num
= 0; /* do not display line number if error */
10308 ret
= tcc_load_archive(s1
, fd
);
10310 #ifdef TCC_TARGET_COFF
10311 if (*(uint16_t *)(&ehdr
) == COFF_C67_MAGIC
) {
10312 ret
= tcc_load_coff(s1
, fd
);
10315 #ifdef TCC_TARGET_PE
10316 if (pe_test_res_file(&ehdr
, ret
)) {
10317 ret
= pe_load_res_file(s1
, fd
);
10321 /* as GNU ld, consider it is an ld script if not recognized */
10323 ret
= tcc_load_ldscript(s1
);
10325 error_noabort("unrecognized file type");
10340 int tcc_add_file(TCCState
*s
, const char *filename
)
10342 return tcc_add_file_internal(s
, filename
, AFF_PRINT_ERROR
);
10345 int tcc_add_library_path(TCCState
*s
, const char *pathname
)
10349 pathname1
= tcc_strdup(pathname
);
10350 dynarray_add((void ***)&s
->library_paths
, &s
->nb_library_paths
, pathname1
);
10354 /* find and load a dll. Return non zero if not found */
10355 /* XXX: add '-rpath' option support ? */
10356 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
)
10361 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
10362 snprintf(buf
, sizeof(buf
), "%s/%s",
10363 s
->library_paths
[i
], filename
);
10364 if (tcc_add_file_internal(s
, buf
, flags
) == 0)
10370 /* the library name is the same as the argument of the '-l' option */
10371 int tcc_add_library(TCCState
*s
, const char *libraryname
)
10376 /* first we look for the dynamic library if not static linking */
10377 if (!s
->static_link
) {
10378 #ifdef TCC_TARGET_PE
10379 snprintf(buf
, sizeof(buf
), "%s.def", libraryname
);
10381 snprintf(buf
, sizeof(buf
), "lib%s.so", libraryname
);
10383 if (tcc_add_dll(s
, buf
, 0) == 0)
10387 /* then we look for the static library */
10388 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
10389 snprintf(buf
, sizeof(buf
), "%s/lib%s.a",
10390 s
->library_paths
[i
], libraryname
);
10391 if (tcc_add_file_internal(s
, buf
, 0) == 0)
10397 int tcc_add_symbol(TCCState
*s
, const char *name
, unsigned long val
)
10399 add_elf_sym(symtab_section
, val
, 0,
10400 ELF32_ST_INFO(STB_GLOBAL
, STT_NOTYPE
), 0,
10405 int tcc_set_output_type(TCCState
*s
, int output_type
)
10409 s
->output_type
= output_type
;
10411 if (!s
->nostdinc
) {
10412 /* default include paths */
10413 /* XXX: reverse order needed if -isystem support */
10414 #ifndef TCC_TARGET_PE
10415 tcc_add_sysinclude_path(s
, "/usr/local/include");
10416 tcc_add_sysinclude_path(s
, "/usr/include");
10418 snprintf(buf
, sizeof(buf
), "%s/include", tcc_lib_path
);
10419 tcc_add_sysinclude_path(s
, buf
);
10420 #ifdef TCC_TARGET_PE
10421 snprintf(buf
, sizeof(buf
), "%s/include/winapi", tcc_lib_path
);
10422 tcc_add_sysinclude_path(s
, buf
);
10426 /* if bound checking, then add corresponding sections */
10427 #ifdef CONFIG_TCC_BCHECK
10428 if (do_bounds_check
) {
10429 /* define symbol */
10430 tcc_define_symbol(s
, "__BOUNDS_CHECKING_ON", NULL
);
10431 /* create bounds sections */
10432 bounds_section
= new_section(s
, ".bounds",
10433 SHT_PROGBITS
, SHF_ALLOC
);
10434 lbounds_section
= new_section(s
, ".lbounds",
10435 SHT_PROGBITS
, SHF_ALLOC
);
10439 if (s
->char_is_unsigned
) {
10440 tcc_define_symbol(s
, "__CHAR_UNSIGNED__", NULL
);
10443 /* add debug sections */
10446 stab_section
= new_section(s
, ".stab", SHT_PROGBITS
, 0);
10447 stab_section
->sh_entsize
= sizeof(Stab_Sym
);
10448 stabstr_section
= new_section(s
, ".stabstr", SHT_STRTAB
, 0);
10449 put_elf_str(stabstr_section
, "");
10450 stab_section
->link
= stabstr_section
;
10451 /* put first entry */
10452 put_stabs("", 0, 0, 0, 0);
10455 /* add libc crt1/crti objects */
10456 #ifndef TCC_TARGET_PE
10457 if ((output_type
== TCC_OUTPUT_EXE
|| output_type
== TCC_OUTPUT_DLL
) &&
10459 if (output_type
!= TCC_OUTPUT_DLL
)
10460 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crt1.o");
10461 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crti.o");
10465 #ifdef TCC_TARGET_PE
10466 snprintf(buf
, sizeof(buf
), "%s/lib", tcc_lib_path
);
10467 tcc_add_library_path(s
, buf
);
10473 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10474 #define FD_INVERT 0x0002 /* invert value before storing */
10476 typedef struct FlagDef
{
10482 static const FlagDef warning_defs
[] = {
10483 { offsetof(TCCState
, warn_unsupported
), 0, "unsupported" },
10484 { offsetof(TCCState
, warn_write_strings
), 0, "write-strings" },
10485 { offsetof(TCCState
, warn_error
), 0, "error" },
10486 { offsetof(TCCState
, warn_implicit_function_declaration
), WD_ALL
,
10487 "implicit-function-declaration" },
10490 static int set_flag(TCCState
*s
, const FlagDef
*flags
, int nb_flags
,
10491 const char *name
, int value
)
10498 if (r
[0] == 'n' && r
[1] == 'o' && r
[2] == '-') {
10502 for(i
= 0, p
= flags
; i
< nb_flags
; i
++, p
++) {
10503 if (!strcmp(r
, p
->name
))
10508 if (p
->flags
& FD_INVERT
)
10510 *(int *)((uint8_t *)s
+ p
->offset
) = value
;
10515 /* set/reset a warning */
10516 int tcc_set_warning(TCCState
*s
, const char *warning_name
, int value
)
10521 if (!strcmp(warning_name
, "all")) {
10522 for(i
= 0, p
= warning_defs
; i
< countof(warning_defs
); i
++, p
++) {
10523 if (p
->flags
& WD_ALL
)
10524 *(int *)((uint8_t *)s
+ p
->offset
) = 1;
10528 return set_flag(s
, warning_defs
, countof(warning_defs
),
10529 warning_name
, value
);
10533 static const FlagDef flag_defs
[] = {
10534 { offsetof(TCCState
, char_is_unsigned
), 0, "unsigned-char" },
10535 { offsetof(TCCState
, char_is_unsigned
), FD_INVERT
, "signed-char" },
10536 { offsetof(TCCState
, nocommon
), FD_INVERT
, "common" },
10537 { offsetof(TCCState
, leading_underscore
), 0, "leading-underscore" },
10540 /* set/reset a flag */
10541 int tcc_set_flag(TCCState
*s
, const char *flag_name
, int value
)
10543 return set_flag(s
, flag_defs
, countof(flag_defs
),
10547 #if !defined(LIBTCC)
10549 static int64_t getclock_us(void)
10554 return (tb
.time
* 1000LL + tb
.millitm
) * 1000LL;
10557 gettimeofday(&tv
, NULL
);
10558 return tv
.tv_sec
* 1000000LL + tv
.tv_usec
;
10564 printf("tcc version " TCC_VERSION
" - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10565 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10566 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-soname name]\n"
10567 " [-static] [infile1 infile2...] [-run infile args...]\n"
10569 "General options:\n"
10570 " -v display current version\n"
10571 " -c compile only - generate an object file\n"
10572 " -o outfile set output filename\n"
10573 " -Bdir set tcc internal library path\n"
10574 " -bench output compilation statistics\n"
10575 " -run run compiled source\n"
10576 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10577 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10578 " -w disable all warnings\n"
10579 "Preprocessor options:\n"
10580 " -E preprocess only\n"
10581 " -Idir add include path 'dir'\n"
10582 " -Dsym[=val] define 'sym' with value 'val'\n"
10583 " -Usym undefine 'sym'\n"
10584 "Linker options:\n"
10585 " -Ldir add library path 'dir'\n"
10586 " -llib link with dynamic or static library 'lib'\n"
10587 " -shared generate a shared library\n"
10588 " -soname set name for shared library to be used at runtime\n"
10589 " -static static linking\n"
10590 " -rdynamic export all global symbols to dynamic linker\n"
10591 " -r generate (relocatable) object file\n"
10592 "Debugger options:\n"
10593 " -g generate runtime debug info\n"
10594 #ifdef CONFIG_TCC_BCHECK
10595 " -b compile with built-in memory and bounds checker (implies -g)\n"
10597 " -bt N show N callers in stack traces\n"
10601 #define TCC_OPTION_HAS_ARG 0x0001
10602 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10604 typedef struct TCCOption
{
10633 TCC_OPTION_nostdinc
,
10634 TCC_OPTION_nostdlib
,
10635 TCC_OPTION_print_search_dirs
,
10636 TCC_OPTION_rdynamic
,
10644 static const TCCOption tcc_options
[] = {
10645 { "h", TCC_OPTION_HELP
, 0 },
10646 { "?", TCC_OPTION_HELP
, 0 },
10647 { "I", TCC_OPTION_I
, TCC_OPTION_HAS_ARG
},
10648 { "D", TCC_OPTION_D
, TCC_OPTION_HAS_ARG
},
10649 { "U", TCC_OPTION_U
, TCC_OPTION_HAS_ARG
},
10650 { "L", TCC_OPTION_L
, TCC_OPTION_HAS_ARG
},
10651 { "B", TCC_OPTION_B
, TCC_OPTION_HAS_ARG
},
10652 { "l", TCC_OPTION_l
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10653 { "bench", TCC_OPTION_bench
, 0 },
10654 { "bt", TCC_OPTION_bt
, TCC_OPTION_HAS_ARG
},
10655 #ifdef CONFIG_TCC_BCHECK
10656 { "b", TCC_OPTION_b
, 0 },
10658 { "g", TCC_OPTION_g
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10659 { "c", TCC_OPTION_c
, 0 },
10660 { "static", TCC_OPTION_static
, 0 },
10661 { "shared", TCC_OPTION_shared
, 0 },
10662 { "soname", TCC_OPTION_soname
, TCC_OPTION_HAS_ARG
},
10663 { "o", TCC_OPTION_o
, TCC_OPTION_HAS_ARG
},
10664 { "run", TCC_OPTION_run
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10665 { "rdynamic", TCC_OPTION_rdynamic
, 0 },
10666 { "r", TCC_OPTION_r
, 0 },
10667 { "Wl,", TCC_OPTION_Wl
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10668 { "W", TCC_OPTION_W
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10669 { "O", TCC_OPTION_O
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10670 { "m", TCC_OPTION_m
, TCC_OPTION_HAS_ARG
},
10671 { "f", TCC_OPTION_f
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10672 { "nostdinc", TCC_OPTION_nostdinc
, 0 },
10673 { "nostdlib", TCC_OPTION_nostdlib
, 0 },
10674 { "print-search-dirs", TCC_OPTION_print_search_dirs
, 0 },
10675 { "v", TCC_OPTION_v
, 0 },
10676 { "w", TCC_OPTION_w
, 0 },
10677 { "pipe", TCC_OPTION_pipe
, 0},
10678 { "E", TCC_OPTION_E
, 0},
10682 /* convert 'str' into an array of space separated strings */
10683 static int expand_args(char ***pargv
, const char *str
)
10692 while (is_space(*str
))
10697 while (*str
!= '\0' && !is_space(*str
))
10700 arg
= tcc_malloc(len
+ 1);
10701 memcpy(arg
, s1
, len
);
10703 dynarray_add((void ***)&argv
, &argc
, arg
);
10709 static char **files
;
10710 static int nb_files
, nb_libraries
;
10711 static int multiple_files
;
10712 static int print_search_dirs
;
10713 static int output_type
;
10714 static int reloc_output
;
10715 static const char *outfile
;
10717 int parse_args(TCCState
*s
, int argc
, char **argv
)
10720 const TCCOption
*popt
;
10721 const char *optarg
, *p1
, *r1
;
10726 if (optind
>= argc
) {
10727 if (nb_files
== 0 && !print_search_dirs
)
10732 r
= argv
[optind
++];
10734 /* add a new file */
10735 dynarray_add((void ***)&files
, &nb_files
, r
);
10736 if (!multiple_files
) {
10738 /* argv[0] will be this file */
10742 /* find option in table (match only the first chars */
10743 popt
= tcc_options
;
10747 error("invalid option -- '%s'", r
);
10760 if (popt
->flags
& TCC_OPTION_HAS_ARG
) {
10761 if (*r1
!= '\0' || (popt
->flags
& TCC_OPTION_NOSEP
)) {
10764 if (optind
>= argc
)
10765 error("argument to '%s' is missing", r
);
10766 optarg
= argv
[optind
++];
10774 switch(popt
->index
) {
10775 case TCC_OPTION_HELP
:
10780 if (tcc_add_include_path(s
, optarg
) < 0)
10781 error("too many include paths");
10786 sym
= (char *)optarg
;
10787 value
= strchr(sym
, '=');
10792 tcc_define_symbol(s
, sym
, value
);
10796 tcc_undefine_symbol(s
, optarg
);
10799 tcc_add_library_path(s
, optarg
);
10802 /* set tcc utilities path (mainly for tcc development) */
10803 tcc_lib_path
= optarg
;
10806 dynarray_add((void ***)&files
, &nb_files
, r
);
10809 case TCC_OPTION_bench
:
10812 case TCC_OPTION_bt
:
10813 num_callers
= atoi(optarg
);
10815 #ifdef CONFIG_TCC_BCHECK
10817 do_bounds_check
= 1;
10825 multiple_files
= 1;
10826 output_type
= TCC_OUTPUT_OBJ
;
10828 case TCC_OPTION_static
:
10829 s
->static_link
= 1;
10831 case TCC_OPTION_shared
:
10832 output_type
= TCC_OUTPUT_DLL
;
10834 case TCC_OPTION_soname
:
10835 s
->soname
= optarg
;
10838 multiple_files
= 1;
10842 /* generate a .o merging several output files */
10844 output_type
= TCC_OUTPUT_OBJ
;
10846 case TCC_OPTION_nostdinc
:
10849 case TCC_OPTION_nostdlib
:
10852 case TCC_OPTION_print_search_dirs
:
10853 print_search_dirs
= 1;
10855 case TCC_OPTION_run
:
10859 argc1
= expand_args(&argv1
, optarg
);
10861 parse_args(s
, argc1
, argv1
);
10863 multiple_files
= 0;
10864 output_type
= TCC_OUTPUT_MEMORY
;
10868 printf("tcc version %s\n", TCC_VERSION
);
10871 if (tcc_set_flag(s
, optarg
, 1) < 0 && s
->warn_unsupported
)
10872 goto unsupported_option
;
10875 if (tcc_set_warning(s
, optarg
, 1) < 0 &&
10876 s
->warn_unsupported
)
10877 goto unsupported_option
;
10882 case TCC_OPTION_rdynamic
:
10885 case TCC_OPTION_Wl
:
10888 if (strstart(optarg
, "-Ttext,", &p
)) {
10889 s
->text_addr
= strtoul(p
, NULL
, 16);
10890 s
->has_text_addr
= 1;
10891 } else if (strstart(optarg
, "--oformat,", &p
)) {
10892 if (strstart(p
, "elf32-", NULL
)) {
10893 s
->output_format
= TCC_OUTPUT_FORMAT_ELF
;
10894 } else if (!strcmp(p
, "binary")) {
10895 s
->output_format
= TCC_OUTPUT_FORMAT_BINARY
;
10897 #ifdef TCC_TARGET_COFF
10898 if (!strcmp(p
, "coff")) {
10899 s
->output_format
= TCC_OUTPUT_FORMAT_COFF
;
10903 error("target %s not found", p
);
10906 error("unsupported linker option '%s'", optarg
);
10911 output_type
= TCC_OUTPUT_PREPROCESS
;
10914 if (s
->warn_unsupported
) {
10915 unsupported_option
:
10916 warning("unsupported option '%s'", r
);
10925 int main(int argc
, char **argv
)
10929 int nb_objfiles
, ret
, optind
;
10930 char objfilename
[1024];
10931 int64_t start_time
= 0;
10934 tcc_lib_path
= w32_tcc_lib_path();
10938 output_type
= TCC_OUTPUT_EXE
;
10940 multiple_files
= 1;
10945 print_search_dirs
= 0;
10948 optind
= parse_args(s
, argc
- 1, argv
+ 1) + 1;
10950 if (print_search_dirs
) {
10951 /* enough for Linux kernel */
10952 printf("install: %s/\n", tcc_lib_path
);
10956 nb_objfiles
= nb_files
- nb_libraries
;
10958 /* if outfile provided without other options, we output an
10960 if (outfile
&& output_type
== TCC_OUTPUT_MEMORY
)
10961 output_type
= TCC_OUTPUT_EXE
;
10963 /* check -c consistency : only single file handled. XXX: checks file type */
10964 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
10965 /* accepts only a single input file */
10966 if (nb_objfiles
!= 1)
10967 error("cannot specify multiple files with -c");
10968 if (nb_libraries
!= 0)
10969 error("cannot specify libraries with -c");
10973 if (output_type
== TCC_OUTPUT_PREPROCESS
) {
10975 s
->outfile
= stdout
;
10977 s
->outfile
= fopen(outfile
, "w");
10979 error("could not open '%s", outfile
);
10981 } else if (output_type
!= TCC_OUTPUT_MEMORY
) {
10983 /* compute default outfile name */
10985 pstrcpy(objfilename
, sizeof(objfilename
), tcc_basename(files
[0]));
10986 ext
= tcc_fileextension(objfilename
);
10987 #ifdef TCC_TARGET_PE
10988 if (output_type
== TCC_OUTPUT_DLL
)
10989 strcpy(ext
, ".dll");
10991 if (output_type
== TCC_OUTPUT_EXE
)
10992 strcpy(ext
, ".exe");
10995 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
&& *ext
)
10998 pstrcpy(objfilename
, sizeof(objfilename
), "a.out");
10999 outfile
= objfilename
;
11004 start_time
= getclock_us();
11007 tcc_set_output_type(s
, output_type
);
11009 /* compile or add each files or library */
11010 for(i
= 0; i
< nb_files
&& ret
== 0; i
++) {
11011 const char *filename
;
11013 filename
= files
[i
];
11014 if (output_type
== TCC_OUTPUT_PREPROCESS
) {
11015 if (tcc_add_file_internal(s
, filename
,
11016 AFF_PRINT_ERROR
| AFF_PREPROCESS
) < 0)
11018 } else if (filename
[0] == '-') {
11019 if (tcc_add_library(s
, filename
+ 2) < 0)
11020 error("cannot find %s", filename
);
11022 if (tcc_add_file(s
, filename
) < 0)
11027 /* free all files */
11035 total_time
= (double)(getclock_us() - start_time
) / 1000000.0;
11036 if (total_time
< 0.001)
11037 total_time
= 0.001;
11038 if (total_bytes
< 1)
11040 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
11041 tok_ident
- TOK_IDENT
, total_lines
, total_bytes
,
11042 total_time
, (int)(total_lines
/ total_time
),
11043 total_bytes
/ total_time
/ 1000000.0);
11046 if (s
->output_type
== TCC_OUTPUT_PREPROCESS
) {
11048 fclose(s
->outfile
);
11049 } else if (s
->output_type
== TCC_OUTPUT_MEMORY
) {
11050 ret
= tcc_run(s
, argc
- optind
, argv
+ optind
);
11052 #ifdef TCC_TARGET_PE
11053 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
11054 ret
= pe_output_file(s
, outfile
);
11058 ret
= tcc_output_file(s
, outfile
) ? 1 : 0;
11061 /* XXX: cannot do it with bound checking because of the malloc hooks */
11062 if (!do_bounds_check
)
11067 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size
, mem_max_size
);