2 * TCC - Tiny C Compiler
4 * Copyright (c) 2001-2004 Fabrice Bellard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #define CONFIG_TCC_STATIC
42 #include <sys/timeb.h>
47 #include <sys/ucontext.h>
51 #endif /* !CONFIG_TCCBOOT */
68 /* preprocessor debug */
70 /* include file debug */
78 /* target selection */
79 //#define TCC_TARGET_I386 /* i386 code generator */
80 //#define TCC_TARGET_ARM /* ARMv4 code generator */
81 //#define TCC_TARGET_C67 /* TMS320C67xx code generator */
83 /* default target is I386 */
84 #if !defined(TCC_TARGET_I386) && !defined(TCC_TARGET_ARM) && \
85 !defined(TCC_TARGET_C67)
86 #define TCC_TARGET_I386
89 #if !defined(WIN32) && !defined(TCC_UCLIBC) && !defined(TCC_TARGET_ARM) && \
90 !defined(TCC_TARGET_C67)
91 #define CONFIG_TCC_BCHECK /* enable bound checking code */
94 #if defined(WIN32) && !defined(TCC_TARGET_PE)
95 #define CONFIG_TCC_STATIC
98 /* define it to include assembler support */
99 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
100 #define CONFIG_TCC_ASM
103 /* object format selection */
104 #if defined(TCC_TARGET_C67)
105 #define TCC_TARGET_COFF
114 /* path to find crt1.o, crti.o and crtn.o. Only needed when generating
115 executables or dlls */
116 #define CONFIG_TCC_CRT_PREFIX "/usr/lib"
118 #define INCLUDE_STACK_SIZE 32
119 #define IFDEF_STACK_SIZE 64
120 #define VSTACK_SIZE 256
121 #define STRING_MAX_SIZE 1024
122 #define PACK_STACK_SIZE 8
124 #define TOK_HASH_SIZE 8192 /* must be a power of two */
125 #define TOK_ALLOC_INCR 512 /* must be a power of two */
126 #define TOK_MAX_SIZE 4 /* token max size in int unit when stored in string */
128 /* token symbol management */
129 typedef struct TokenSym
{
130 struct TokenSym
*hash_next
;
131 struct Sym
*sym_define
; /* direct pointer to define */
132 struct Sym
*sym_label
; /* direct pointer to label */
133 struct Sym
*sym_struct
; /* direct pointer to structure */
134 struct Sym
*sym_identifier
; /* direct pointer to identifier */
135 int tok
; /* token number */
141 typedef unsigned short nwchar_t
;
143 typedef int nwchar_t
;
146 typedef struct CString
{
147 int size
; /* size in bytes */
148 void *data
; /* either 'char *' or 'nwchar_t *' */
150 void *data_allocated
; /* if non NULL, data has been malloced */
153 /* type definition */
154 typedef struct CType
{
160 typedef union CValue
{
166 unsigned int ul
; /* address (should be unsigned long on 64 bit cpu) */
168 unsigned long long ull
;
169 struct CString
*cstr
;
175 typedef struct SValue
{
176 CType type
; /* type */
177 unsigned short r
; /* register + flags */
178 unsigned short r2
; /* second register, used for 'long long'
179 type. If not used, set to VT_CONST */
180 CValue c
; /* constant, if VT_CONST */
181 struct Sym
*sym
; /* symbol, if (VT_SYM | VT_CONST) */
184 /* symbol management */
186 int v
; /* symbol token */
187 int r
; /* associated register */
188 int c
; /* associated number */
189 CType type
; /* associated type */
190 struct Sym
*next
; /* next related symbol */
191 struct Sym
*prev
; /* prev symbol in stack */
192 struct Sym
*prev_tok
; /* previous symbol for this token */
195 /* section definition */
196 /* XXX: use directly ELF structure for parameters ? */
197 /* special flag to indicate that the section should not be linked to
199 #define SHF_PRIVATE 0x80000000
201 typedef struct Section
{
202 unsigned long data_offset
; /* current data offset */
203 unsigned char *data
; /* section data */
204 unsigned long data_allocated
; /* used for realloc() handling */
205 int sh_name
; /* elf section name (only used during output) */
206 int sh_num
; /* elf section number */
207 int sh_type
; /* elf section type */
208 int sh_flags
; /* elf section flags */
209 int sh_info
; /* elf section info */
210 int sh_addralign
; /* elf section alignment */
211 int sh_entsize
; /* elf entry size */
212 unsigned long sh_size
; /* section size (only used during output) */
213 unsigned long sh_addr
; /* address at which the section is relocated */
214 unsigned long sh_offset
; /* file offset */
215 int nb_hashed_syms
; /* used to resize the hash table */
216 struct Section
*link
; /* link to another section */
217 struct Section
*reloc
; /* corresponding section for relocation, if any */
218 struct Section
*hash
; /* hash table for symbols */
219 struct Section
*next
;
220 char name
[1]; /* section name */
223 typedef struct DLLReference
{
228 /* GNUC attribute definition */
229 typedef struct AttributeDef
{
233 unsigned char func_call
; /* FUNC_CDECL, FUNC_STDCALL, FUNC_FASTCALLx */
234 unsigned char dllexport
;
237 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
238 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
239 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
241 /* stored in 'Sym.c' field */
242 #define FUNC_NEW 1 /* ansi function prototype */
243 #define FUNC_OLD 2 /* old function prototype */
244 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
246 /* stored in 'Sym.r' field */
247 #define FUNC_CDECL 0 /* standard c call */
248 #define FUNC_STDCALL 1 /* pascal c call */
249 #define FUNC_FASTCALL1 2 /* first param in %eax */
250 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
251 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
252 #define FUNC_FASTCALLW 5 /* first parameter in %ecx, %edx */
254 /* field 'Sym.t' for macros */
255 #define MACRO_OBJ 0 /* object like macro */
256 #define MACRO_FUNC 1 /* function like macro */
258 /* field 'Sym.r' for C labels */
259 #define LABEL_DEFINED 0 /* label is defined */
260 #define LABEL_FORWARD 1 /* label is forward defined */
261 #define LABEL_DECLARED 2 /* label is declared but never used */
263 /* type_decl() types */
264 #define TYPE_ABSTRACT 1 /* type without variable */
265 #define TYPE_DIRECT 2 /* type with variable */
267 #define IO_BUF_SIZE 8192
269 typedef struct BufferedFile
{
273 int line_num
; /* current line number - here to simplify code */
274 int ifndef_macro
; /* #ifndef macro / #endif search */
275 int ifndef_macro_saved
; /* saved ifndef_macro */
276 int *ifdef_stack_ptr
; /* ifdef_stack value at the start of the file */
277 char inc_type
; /* type of include */
278 char inc_filename
[512]; /* filename specified by the user */
279 char filename
[1024]; /* current filename - here to simplify code */
280 unsigned char buffer
[IO_BUF_SIZE
+ 1]; /* extra size for CH_EOB char */
283 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
284 #define CH_EOF (-1) /* end of file */
286 /* parsing state (used to save parser state to reparse part of the
287 source several times) */
288 typedef struct ParseState
{
295 /* used to record tokens */
296 typedef struct TokenString
{
303 /* include file cache, used to find files faster and also to eliminate
304 inclusion if the include file is protected by #ifndef ... #endif */
305 typedef struct CachedInclude
{
307 int hash_next
; /* -1 if none */
308 char type
; /* '"' or '>' to give include type */
309 char filename
[1]; /* path specified in #include */
312 #define CACHED_INCLUDES_HASH_SIZE 512
315 static struct BufferedFile
*file
;
318 static CString tokcstr
; /* current parsed string, if any */
319 /* additional informations about token */
320 static int tok_flags
;
321 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
322 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
323 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
325 static int *macro_ptr
, *macro_ptr_allocated
;
326 static int *unget_saved_macro_ptr
;
327 static int unget_saved_buffer
[TOK_MAX_SIZE
+ 1];
328 static int unget_buffer_enabled
;
329 static int parse_flags
;
330 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
331 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
332 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
333 token. line feed is also
335 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
337 static Section
*text_section
, *data_section
, *bss_section
; /* predefined sections */
338 static Section
*cur_text_section
; /* current section where function code is
340 #ifdef CONFIG_TCC_ASM
341 static Section
*last_text_section
; /* to handle .previous asm directive */
343 /* bound check related sections */
344 static Section
*bounds_section
; /* contains global data bound description */
345 static Section
*lbounds_section
; /* contains local data bound description */
346 /* symbol sections */
347 static Section
*symtab_section
, *strtab_section
;
350 static Section
*stab_section
, *stabstr_section
;
352 /* loc : local variable index
353 ind : output code index
355 anon_sym: anonymous symbol index
357 static int rsym
, anon_sym
, ind
, loc
;
358 /* expression generation modifiers */
359 static int const_wanted
; /* true if constant wanted */
360 static int nocode_wanted
; /* true if no code generation wanted for an expression */
361 static int global_expr
; /* true if compound literals must be allocated
362 globally (used during initializers parsing */
363 static CType func_vt
; /* current function return type (used by return
366 static int last_line_num
, last_ind
, func_ind
; /* debug last line number and pc */
367 static int tok_ident
;
368 static TokenSym
**table_ident
;
369 static TokenSym
*hash_ident
[TOK_HASH_SIZE
];
370 static char token_buf
[STRING_MAX_SIZE
+ 1];
371 static char *funcname
;
372 static Sym
*global_stack
, *local_stack
;
373 static Sym
*define_stack
;
374 static Sym
*global_label_stack
, *local_label_stack
;
375 /* symbol allocator */
376 #define SYM_POOL_NB (8192 / sizeof(Sym))
377 static Sym
*sym_free_first
;
379 static SValue vstack
[VSTACK_SIZE
], *vtop
;
380 /* some predefined types */
381 static CType char_pointer_type
, func_old_type
, int_type
;
382 /* true if isid(c) || isnum(c) */
383 static unsigned char isidnum_table
[256];
385 /* compile with debug symbol (and use them if error during execution) */
386 static int do_debug
= 0;
388 /* compile with built-in memory and bounds checker */
389 static int do_bounds_check
= 0;
391 /* display benchmark infos */
393 static int do_bench
= 0;
395 static int total_lines
;
396 static int total_bytes
;
398 /* use GNU C extensions */
399 static int gnu_ext
= 1;
401 /* use Tiny C extensions */
402 static int tcc_ext
= 1;
404 /* max number of callers shown if error */
405 static int num_callers
= 6;
406 static const char **rt_bound_error_msg
;
408 /* XXX: get rid of this ASAP */
409 static struct TCCState
*tcc_state
;
411 /* give the path of the tcc libraries */
412 static const char *tcc_lib_path
= CONFIG_TCCDIR
;
417 BufferedFile
**include_stack_ptr
;
418 int *ifdef_stack_ptr
;
420 /* include file handling */
421 char **include_paths
;
422 int nb_include_paths
;
423 char **sysinclude_paths
;
424 int nb_sysinclude_paths
;
425 CachedInclude
**cached_includes
;
426 int nb_cached_includes
;
428 char **library_paths
;
429 int nb_library_paths
;
431 /* array of all loaded dlls (including those referenced by loaded
433 DLLReference
**loaded_dlls
;
438 int nb_sections
; /* number of sections, including first dummy section */
443 unsigned long *got_offsets
;
445 /* give the correspondance from symtab indexes to dynsym indexes */
446 int *symtab_to_dynsym
;
448 /* temporary dynamic symbol sections (for dll loading) */
449 Section
*dynsymtab_section
;
450 /* exported dynamic symbol section */
453 int nostdinc
; /* if true, no standard headers are added */
454 int nostdlib
; /* if true, no standard libraries are added */
456 int nocommon
; /* if true, do not use common symbols for .bss data */
458 /* if true, static linking is performed */
461 /* if true, all symbols are exported */
464 /* if true, only link in referenced objects from archive */
467 /* address of text section */
468 unsigned long text_addr
;
471 /* output format, see TCC_OUTPUT_FORMAT_xxx */
474 /* C language options */
475 int char_is_unsigned
;
476 int leading_underscore
;
478 /* warning switches */
479 int warn_write_strings
;
480 int warn_unsupported
;
483 int warn_implicit_function_declaration
;
487 void (*error_func
)(void *opaque
, const char *msg
);
488 int error_set_jmp_enabled
;
489 jmp_buf error_jmp_buf
;
492 /* tiny assembler state */
495 /* see include_stack_ptr */
496 BufferedFile
*include_stack
[INCLUDE_STACK_SIZE
];
498 /* see ifdef_stack_ptr */
499 int ifdef_stack
[IFDEF_STACK_SIZE
];
501 /* see cached_includes */
502 int cached_includes_hash
[CACHED_INCLUDES_HASH_SIZE
];
505 int pack_stack
[PACK_STACK_SIZE
];
509 /* The current value can be: */
510 #define VT_VALMASK 0x00ff
511 #define VT_CONST 0x00f0 /* constant in vc
512 (must be first non register value) */
513 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
514 #define VT_LOCAL 0x00f2 /* offset on stack */
515 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
516 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
517 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
518 #define VT_LVAL 0x0100 /* var is an lvalue */
519 #define VT_SYM 0x0200 /* a symbol value is added */
520 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
521 char/short stored in integer registers) */
522 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
523 dereferencing value */
524 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
525 bounding function call point is in vc */
526 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
527 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
528 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
529 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
532 #define VT_INT 0 /* integer type */
533 #define VT_BYTE 1 /* signed byte type */
534 #define VT_SHORT 2 /* short type */
535 #define VT_VOID 3 /* void type */
536 #define VT_PTR 4 /* pointer */
537 #define VT_ENUM 5 /* enum definition */
538 #define VT_FUNC 6 /* function type */
539 #define VT_STRUCT 7 /* struct/union definition */
540 #define VT_FLOAT 8 /* IEEE float */
541 #define VT_DOUBLE 9 /* IEEE double */
542 #define VT_LDOUBLE 10 /* IEEE long double */
543 #define VT_BOOL 11 /* ISOC99 boolean type */
544 #define VT_LLONG 12 /* 64 bit integer */
545 #define VT_LONG 13 /* long integer (NEVER USED as type, only
547 #define VT_BTYPE 0x000f /* mask for basic type */
548 #define VT_UNSIGNED 0x0010 /* unsigned type */
549 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
550 #define VT_BITFIELD 0x0040 /* bitfield modifier */
551 #define VT_CONSTANT 0x0800 /* const modifier */
552 #define VT_VOLATILE 0x1000 /* volatile modifier */
553 #define VT_SIGNED 0x2000 /* signed type */
556 #define VT_EXTERN 0x00000080 /* extern definition */
557 #define VT_STATIC 0x00000100 /* static variable */
558 #define VT_TYPEDEF 0x00000200 /* typedef definition */
559 #define VT_INLINE 0x00000400 /* inline definition */
561 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
563 /* type mask (except storage) */
564 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
565 #define VT_TYPE (~(VT_STORAGE))
569 /* warning: the following compare tokens depend on i386 asm code */
581 #define TOK_LAND 0xa0
585 #define TOK_MID 0xa3 /* inc/dec, to void constant */
587 #define TOK_UDIV 0xb0 /* unsigned division */
588 #define TOK_UMOD 0xb1 /* unsigned modulo */
589 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
590 #define TOK_CINT 0xb3 /* number in tokc */
591 #define TOK_CCHAR 0xb4 /* char constant in tokc */
592 #define TOK_STR 0xb5 /* pointer to string in tokc */
593 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
594 #define TOK_LCHAR 0xb7
595 #define TOK_LSTR 0xb8
596 #define TOK_CFLOAT 0xb9 /* float constant */
597 #define TOK_LINENUM 0xba /* line number info */
598 #define TOK_CDOUBLE 0xc0 /* double constant */
599 #define TOK_CLDOUBLE 0xc1 /* long double constant */
600 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
601 #define TOK_ADDC1 0xc3 /* add with carry generation */
602 #define TOK_ADDC2 0xc4 /* add with carry use */
603 #define TOK_SUBC1 0xc5 /* add with carry generation */
604 #define TOK_SUBC2 0xc6 /* add with carry use */
605 #define TOK_CUINT 0xc8 /* unsigned int constant */
606 #define TOK_CLLONG 0xc9 /* long long constant */
607 #define TOK_CULLONG 0xca /* unsigned long long constant */
608 #define TOK_ARROW 0xcb
609 #define TOK_DOTS 0xcc /* three dots */
610 #define TOK_SHR 0xcd /* unsigned shift right */
611 #define TOK_PPNUM 0xce /* preprocessor number */
613 #define TOK_SHL 0x01 /* shift left */
614 #define TOK_SAR 0x02 /* signed shift right */
616 /* assignement operators : normal operator or 0x80 */
617 #define TOK_A_MOD 0xa5
618 #define TOK_A_AND 0xa6
619 #define TOK_A_MUL 0xaa
620 #define TOK_A_ADD 0xab
621 #define TOK_A_SUB 0xad
622 #define TOK_A_DIV 0xaf
623 #define TOK_A_XOR 0xde
624 #define TOK_A_OR 0xfc
625 #define TOK_A_SHL 0x81
626 #define TOK_A_SAR 0x82
629 #define offsetof(type, field) ((size_t) &((type *)0)->field)
633 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
636 /* WARNING: the content of this string encodes token numbers */
637 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";
639 #define TOK_EOF (-1) /* end of file */
640 #define TOK_LINEFEED 10 /* line feed */
642 /* all identificators and strings have token above that */
643 #define TOK_IDENT 256
645 /* only used for i386 asm opcodes definitions */
646 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
649 DEF(TOK_ASM_ ## x ## b, #x "b") \
650 DEF(TOK_ASM_ ## x ## w, #x "w") \
651 DEF(TOK_ASM_ ## x ## l, #x "l") \
652 DEF(TOK_ASM_ ## x, #x)
655 DEF(TOK_ASM_ ## x ## w, #x "w") \
656 DEF(TOK_ASM_ ## x ## l, #x "l") \
657 DEF(TOK_ASM_ ## x, #x)
660 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
661 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
662 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
663 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
666 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
667 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
670 #define DEF_ASMTEST(x) \
702 #define TOK_ASM_int TOK_INT
705 TOK_LAST
= TOK_IDENT
- 1,
706 #define DEF(id, str) id,
711 static const char tcc_keywords
[] =
712 #define DEF(id, str) str "\0"
717 #define TOK_UIDENT TOK_DEFINE
720 int __stdcall
GetModuleFileNameA(void *, char *, int);
721 void *__stdcall
GetProcAddress(void *, const char *);
722 void *__stdcall
GetModuleHandleA(const char *);
723 void *__stdcall
LoadLibraryA(const char *);
724 int __stdcall
FreeConsole(void);
726 #define snprintf _snprintf
727 #define vsnprintf _vsnprintf
729 #define strtold (long double)strtod
730 #define strtof (float)strtod
731 #define strtoll (long long)strtol
733 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__)
734 /* currently incorrect */
735 long double strtold(const char *nptr
, char **endptr
)
737 return (long double)strtod(nptr
, endptr
);
739 float strtof(const char *nptr
, char **endptr
)
741 return (float)strtod(nptr
, endptr
);
744 /* XXX: need to define this to use them in non ISOC99 context */
745 extern float strtof (const char *__nptr
, char **__endptr
);
746 extern long double strtold (const char *__nptr
, char **__endptr
);
749 static char *pstrcpy(char *buf
, int buf_size
, const char *s
);
750 static char *pstrcat(char *buf
, int buf_size
, const char *s
);
751 static const char *tcc_basename(const char *name
);
753 static void next(void);
754 static void next_nomacro(void);
755 static void parse_expr_type(CType
*type
);
756 static void expr_type(CType
*type
);
757 static void unary_type(CType
*type
);
758 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
759 int case_reg
, int is_expr
);
760 static int expr_const(void);
761 static void expr_eq(void);
762 static void gexpr(void);
763 static void gen_inline_functions(void);
764 static void decl(int l
);
765 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
766 int first
, int size_only
);
767 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
768 int has_init
, int v
, int scope
);
770 void gv2(int rc1
, int rc2
);
771 void move_reg(int r
, int s
);
772 void save_regs(int n
);
773 void save_reg(int r
);
778 int get_reg_ex(int rc
,int rc2
);
781 struct macro_level
*prev
;
785 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
786 const int *macro_str
, struct macro_level
**can_read_stream
);
788 void force_charshort_cast(int t
);
789 static void gen_cast(CType
*type
);
791 static Sym
*sym_find(int v
);
792 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
);
795 static int type_size(CType
*type
, int *a
);
796 static inline CType
*pointed_type(CType
*type
);
797 static int pointed_size(CType
*type
);
798 static int lvalue_type(int t
);
799 static int parse_btype(CType
*type
, AttributeDef
*ad
);
800 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
);
801 static int is_compatible_types(CType
*type1
, CType
*type2
);
803 int ieee_finite(double d
);
804 void error(const char *fmt
, ...);
808 void lexpand_nr(void);
809 static void vpush_global_sym(CType
*type
, int v
);
810 void vset(CType
*type
, int r
, int v
);
811 void type_to_str(char *buf
, int buf_size
,
812 CType
*type
, const char *varstr
);
813 char *get_tok_str(int v
, CValue
*cv
);
814 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
815 unsigned long offset
, unsigned long size
);
816 static Sym
*external_global_sym(int v
, CType
*type
, int r
);
818 /* section generation */
819 static void section_realloc(Section
*sec
, unsigned long new_size
);
820 static void *section_ptr_add(Section
*sec
, unsigned long size
);
821 static void put_extern_sym(Sym
*sym
, Section
*section
,
822 unsigned long value
, unsigned long size
);
823 static void greloc(Section
*s
, Sym
*sym
, unsigned long addr
, int type
);
824 static int put_elf_str(Section
*s
, const char *sym
);
825 static int put_elf_sym(Section
*s
,
826 unsigned long value
, unsigned long size
,
827 int info
, int other
, int shndx
, const char *name
);
828 static int add_elf_sym(Section
*s
, unsigned long value
, unsigned long size
,
829 int info
, int other
, int sh_num
, const char *name
);
830 static void put_elf_reloc(Section
*symtab
, Section
*s
, unsigned long offset
,
831 int type
, int symbol
);
832 static void put_stabs(const char *str
, int type
, int other
, int desc
,
833 unsigned long value
);
834 static void put_stabs_r(const char *str
, int type
, int other
, int desc
,
835 unsigned long value
, Section
*sec
, int sym_index
);
836 static void put_stabn(int type
, int other
, int desc
, int value
);
837 static void put_stabd(int type
, int other
, int desc
);
838 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
);
840 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
841 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
842 static int tcc_add_file_internal(TCCState
*s
, const char *filename
, int flags
);
845 int tcc_output_coff(TCCState
*s1
, FILE *f
);
848 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
);
849 int pe_load_def_file(struct TCCState
*s1
, FILE *fp
);
850 void pe_setup_paths(struct TCCState
*s1
, int *p_output_type
, const char **p_outfile
, char *first_file
);
851 unsigned long pe_add_runtime(struct TCCState
*s1
);
852 int tcc_output_pe(struct TCCState
*s1
, const char *filename
);
856 #ifdef CONFIG_TCC_ASM
858 typedef struct ExprValue
{
863 #define MAX_ASM_OPERANDS 30
865 typedef struct ASMOperand
{
866 int id
; /* GCC 3 optionnal identifier (0 if number only supported */
868 char asm_str
[16]; /* computed asm string for operand */
869 SValue
*vt
; /* C value of the expression */
870 int ref_index
; /* if >= 0, gives reference to a output constraint */
871 int input_index
; /* if >= 0, gives reference to an input constraint */
872 int priority
; /* priority, used to assign registers */
873 int reg
; /* if >= 0, register number used for this operand */
874 int is_llong
; /* true if double register value */
875 int is_memory
; /* true if memory operand */
876 int is_rw
; /* for '+' modifier */
879 static void asm_expr(TCCState
*s1
, ExprValue
*pe
);
880 static int asm_int_expr(TCCState
*s1
);
881 static int find_constraint(ASMOperand
*operands
, int nb_operands
,
882 const char *name
, const char **pp
);
884 static int tcc_assemble(TCCState
*s1
, int do_preprocess
);
888 static void asm_instr(void);
889 static void asm_global_instr(void);
891 /* true if float/double/long double type */
892 static inline int is_float(int t
)
896 return bt
== VT_LDOUBLE
|| bt
== VT_DOUBLE
|| bt
== VT_FLOAT
;
899 #ifdef TCC_TARGET_I386
900 #include "i386-gen.c"
903 #ifdef TCC_TARGET_ARM
907 #ifdef TCC_TARGET_C67
911 #ifdef CONFIG_TCC_STATIC
913 #define RTLD_LAZY 0x001
914 #define RTLD_NOW 0x002
915 #define RTLD_GLOBAL 0x100
916 #define RTLD_DEFAULT NULL
918 /* dummy function for profiling */
919 void *dlopen(const char *filename
, int flag
)
924 const char *dlerror(void)
929 typedef struct TCCSyms
{
934 #define TCCSYM(a) { #a, &a, },
936 /* add the symbol you want here if no dynamic linking is done */
937 static TCCSyms tcc_syms
[] = {
938 #if !defined(CONFIG_TCCBOOT)
947 void *resolve_sym(TCCState
*s1
, const char *symbol
, int type
)
951 while (p
->str
!= NULL
) {
952 if (!strcmp(p
->str
, symbol
))
959 #elif !defined(WIN32)
963 void *resolve_sym(TCCState
*s1
, const char *sym
, int type
)
965 return dlsym(RTLD_DEFAULT
, sym
);
970 /********************************************************/
972 /* we use our own 'finite' function to avoid potential problems with
973 non standard math libs */
974 /* XXX: endianness dependent */
975 int ieee_finite(double d
)
978 return ((unsigned)((p
[1] | 0x800fffff) + 1)) >> 31;
981 /* copy a string and truncate it. */
982 static char *pstrcpy(char *buf
, int buf_size
, const char *s
)
989 q_end
= buf
+ buf_size
- 1;
1001 /* strcat and truncate. */
1002 static char *pstrcat(char *buf
, int buf_size
, const char *s
)
1007 pstrcpy(buf
+ len
, buf_size
- len
, s
);
1011 static int strstart(const char *str
, const char *val
, const char **ptr
)
1016 while (*q
!= '\0') {
1027 /* memory management */
1033 static inline void tcc_free(void *ptr
)
1036 mem_cur_size
-= malloc_usable_size(ptr
);
1041 static void *tcc_malloc(unsigned long size
)
1046 error("memory full");
1048 mem_cur_size
+= malloc_usable_size(ptr
);
1049 if (mem_cur_size
> mem_max_size
)
1050 mem_max_size
= mem_cur_size
;
1055 static void *tcc_mallocz(unsigned long size
)
1058 ptr
= tcc_malloc(size
);
1059 memset(ptr
, 0, size
);
1063 static inline void *tcc_realloc(void *ptr
, unsigned long size
)
1067 mem_cur_size
-= malloc_usable_size(ptr
);
1069 ptr1
= realloc(ptr
, size
);
1071 /* NOTE: count not correct if alloc error, but not critical */
1072 mem_cur_size
+= malloc_usable_size(ptr1
);
1073 if (mem_cur_size
> mem_max_size
)
1074 mem_max_size
= mem_cur_size
;
1079 static char *tcc_strdup(const char *str
)
1082 ptr
= tcc_malloc(strlen(str
) + 1);
1087 #define free(p) use_tcc_free(p)
1088 #define malloc(s) use_tcc_malloc(s)
1089 #define realloc(p, s) use_tcc_realloc(p, s)
1091 static void dynarray_add(void ***ptab
, int *nb_ptr
, void *data
)
1098 /* every power of two we double array size */
1099 if ((nb
& (nb
- 1)) == 0) {
1104 pp
= tcc_realloc(pp
, nb_alloc
* sizeof(void *));
1106 error("memory full");
1113 /* symbol allocator */
1114 static Sym
*__sym_malloc(void)
1116 Sym
*sym_pool
, *sym
, *last_sym
;
1119 sym_pool
= tcc_malloc(SYM_POOL_NB
* sizeof(Sym
));
1121 last_sym
= sym_free_first
;
1123 for(i
= 0; i
< SYM_POOL_NB
; i
++) {
1124 sym
->next
= last_sym
;
1128 sym_free_first
= last_sym
;
1132 static inline Sym
*sym_malloc(void)
1135 sym
= sym_free_first
;
1137 sym
= __sym_malloc();
1138 sym_free_first
= sym
->next
;
1142 static inline void sym_free(Sym
*sym
)
1144 sym
->next
= sym_free_first
;
1145 sym_free_first
= sym
;
1148 Section
*new_section(TCCState
*s1
, const char *name
, int sh_type
, int sh_flags
)
1152 sec
= tcc_mallocz(sizeof(Section
) + strlen(name
));
1153 strcpy(sec
->name
, name
);
1154 sec
->sh_type
= sh_type
;
1155 sec
->sh_flags
= sh_flags
;
1162 sec
->sh_addralign
= 4;
1165 sec
->sh_addralign
= 1;
1168 sec
->sh_addralign
= 32; /* default conservative alignment */
1172 /* only add section if not private */
1173 if (!(sh_flags
& SHF_PRIVATE
)) {
1174 sec
->sh_num
= s1
->nb_sections
;
1175 dynarray_add((void ***)&s1
->sections
, &s1
->nb_sections
, sec
);
1180 static void free_section(Section
*s
)
1186 /* realloc section and set its content to zero */
1187 static void section_realloc(Section
*sec
, unsigned long new_size
)
1190 unsigned char *data
;
1192 size
= sec
->data_allocated
;
1195 while (size
< new_size
)
1197 data
= tcc_realloc(sec
->data
, size
);
1199 error("memory full");
1200 memset(data
+ sec
->data_allocated
, 0, size
- sec
->data_allocated
);
1202 sec
->data_allocated
= size
;
1205 /* reserve at least 'size' bytes in section 'sec' from
1206 sec->data_offset. */
1207 static void *section_ptr_add(Section
*sec
, unsigned long size
)
1209 unsigned long offset
, offset1
;
1211 offset
= sec
->data_offset
;
1212 offset1
= offset
+ size
;
1213 if (offset1
> sec
->data_allocated
)
1214 section_realloc(sec
, offset1
);
1215 sec
->data_offset
= offset1
;
1216 return sec
->data
+ offset
;
1219 /* return a reference to a section, and create it if it does not
1221 Section
*find_section(TCCState
*s1
, const char *name
)
1225 for(i
= 1; i
< s1
->nb_sections
; i
++) {
1226 sec
= s1
->sections
[i
];
1227 if (!strcmp(name
, sec
->name
))
1230 /* sections are created as PROGBITS */
1231 return new_section(s1
, name
, SHT_PROGBITS
, SHF_ALLOC
);
1234 #define SECTION_ABS ((void *)1)
1236 /* update sym->c so that it points to an external symbol in section
1237 'section' with value 'value' */
1238 static void put_extern_sym2(Sym
*sym
, Section
*section
,
1239 unsigned long value
, unsigned long size
,
1240 int can_add_underscore
)
1242 int sym_type
, sym_bind
, sh_num
, info
;
1247 if (section
== NULL
)
1249 else if (section
== SECTION_ABS
)
1252 sh_num
= section
->sh_num
;
1254 if ((sym
->type
.t
& VT_BTYPE
) == VT_FUNC
)
1255 sym_type
= STT_FUNC
;
1257 sym_type
= STT_OBJECT
;
1258 if (sym
->type
.t
& VT_STATIC
)
1259 sym_bind
= STB_LOCAL
;
1261 sym_bind
= STB_GLOBAL
;
1263 name
= get_tok_str(sym
->v
, NULL
);
1264 #ifdef CONFIG_TCC_BCHECK
1265 if (do_bounds_check
) {
1268 /* XXX: avoid doing that for statics ? */
1269 /* if bound checking is activated, we change some function
1270 names by adding the "__bound" prefix */
1273 /* XXX: we rely only on malloc hooks */
1285 strcpy(buf
, "__bound_");
1292 if (tcc_state
->leading_underscore
&& can_add_underscore
) {
1294 pstrcpy(buf1
+ 1, sizeof(buf1
) - 1, name
);
1297 info
= ELF32_ST_INFO(sym_bind
, sym_type
);
1298 sym
->c
= add_elf_sym(symtab_section
, value
, size
, info
, 0, sh_num
, name
);
1300 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
1301 esym
->st_value
= value
;
1302 esym
->st_size
= size
;
1303 esym
->st_shndx
= sh_num
;
1307 static void put_extern_sym(Sym
*sym
, Section
*section
,
1308 unsigned long value
, unsigned long size
)
1310 put_extern_sym2(sym
, section
, value
, size
, 1);
1313 /* add a new relocation entry to symbol 'sym' in section 's' */
1314 static void greloc(Section
*s
, Sym
*sym
, unsigned long offset
, int type
)
1317 put_extern_sym(sym
, NULL
, 0, 0);
1318 /* now we can add ELF relocation info */
1319 put_elf_reloc(symtab_section
, s
, offset
, type
, sym
->c
);
1322 static inline int isid(int c
)
1324 return (c
>= 'a' && c
<= 'z') ||
1325 (c
>= 'A' && c
<= 'Z') ||
1329 static inline int isnum(int c
)
1331 return c
>= '0' && c
<= '9';
1334 static inline int isoct(int c
)
1336 return c
>= '0' && c
<= '7';
1339 static inline int toup(int c
)
1341 if (c
>= 'a' && c
<= 'z')
1342 return c
- 'a' + 'A';
1347 static void strcat_vprintf(char *buf
, int buf_size
, const char *fmt
, va_list ap
)
1351 vsnprintf(buf
+ len
, buf_size
- len
, fmt
, ap
);
1354 static void strcat_printf(char *buf
, int buf_size
, const char *fmt
, ...)
1358 strcat_vprintf(buf
, buf_size
, fmt
, ap
);
1362 void error1(TCCState
*s1
, int is_warning
, const char *fmt
, va_list ap
)
1369 for(f
= s1
->include_stack
; f
< s1
->include_stack_ptr
; f
++)
1370 strcat_printf(buf
, sizeof(buf
), "In file included from %s:%d:\n",
1371 (*f
)->filename
, (*f
)->line_num
);
1372 if (file
->line_num
> 0) {
1373 strcat_printf(buf
, sizeof(buf
),
1374 "%s:%d: ", file
->filename
, file
->line_num
);
1376 strcat_printf(buf
, sizeof(buf
),
1377 "%s: ", file
->filename
);
1380 strcat_printf(buf
, sizeof(buf
),
1384 strcat_printf(buf
, sizeof(buf
), "warning: ");
1385 strcat_vprintf(buf
, sizeof(buf
), fmt
, ap
);
1387 if (!s1
->error_func
) {
1388 /* default case: stderr */
1389 fprintf(stderr
, "%s\n", buf
);
1391 s1
->error_func(s1
->error_opaque
, buf
);
1393 if (!is_warning
|| s1
->warn_error
)
1398 void tcc_set_error_func(TCCState
*s
, void *error_opaque
,
1399 void (*error_func
)(void *opaque
, const char *msg
))
1401 s
->error_opaque
= error_opaque
;
1402 s
->error_func
= error_func
;
1406 /* error without aborting current compilation */
1407 void error_noabort(const char *fmt
, ...)
1409 TCCState
*s1
= tcc_state
;
1413 error1(s1
, 0, fmt
, ap
);
1417 void error(const char *fmt
, ...)
1419 TCCState
*s1
= tcc_state
;
1423 error1(s1
, 0, fmt
, ap
);
1425 /* better than nothing: in some cases, we accept to handle errors */
1426 if (s1
->error_set_jmp_enabled
) {
1427 longjmp(s1
->error_jmp_buf
, 1);
1429 /* XXX: eliminate this someday */
1434 void expect(const char *msg
)
1436 error("%s expected", msg
);
1439 void warning(const char *fmt
, ...)
1441 TCCState
*s1
= tcc_state
;
1448 error1(s1
, 1, fmt
, ap
);
1455 error("'%c' expected", c
);
1459 static void test_lvalue(void)
1461 if (!(vtop
->r
& VT_LVAL
))
1465 /* allocate a new token */
1466 static TokenSym
*tok_alloc_new(TokenSym
**pts
, const char *str
, int len
)
1468 TokenSym
*ts
, **ptable
;
1471 if (tok_ident
>= SYM_FIRST_ANOM
)
1472 error("memory full");
1474 /* expand token table if needed */
1475 i
= tok_ident
- TOK_IDENT
;
1476 if ((i
% TOK_ALLOC_INCR
) == 0) {
1477 ptable
= tcc_realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
1479 error("memory full");
1480 table_ident
= ptable
;
1483 ts
= tcc_malloc(sizeof(TokenSym
) + len
);
1484 table_ident
[i
] = ts
;
1485 ts
->tok
= tok_ident
++;
1486 ts
->sym_define
= NULL
;
1487 ts
->sym_label
= NULL
;
1488 ts
->sym_struct
= NULL
;
1489 ts
->sym_identifier
= NULL
;
1491 ts
->hash_next
= NULL
;
1492 memcpy(ts
->str
, str
, len
);
1493 ts
->str
[len
] = '\0';
1498 #define TOK_HASH_INIT 1
1499 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1501 /* find a token and add it if not found */
1502 static TokenSym
*tok_alloc(const char *str
, int len
)
1504 TokenSym
*ts
, **pts
;
1510 h
= TOK_HASH_FUNC(h
, ((unsigned char *)str
)[i
]);
1511 h
&= (TOK_HASH_SIZE
- 1);
1513 pts
= &hash_ident
[h
];
1518 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
1520 pts
= &(ts
->hash_next
);
1522 return tok_alloc_new(pts
, str
, len
);
1525 /* CString handling */
1527 static void cstr_realloc(CString
*cstr
, int new_size
)
1532 size
= cstr
->size_allocated
;
1534 size
= 8; /* no need to allocate a too small first string */
1535 while (size
< new_size
)
1537 data
= tcc_realloc(cstr
->data_allocated
, size
);
1539 error("memory full");
1540 cstr
->data_allocated
= data
;
1541 cstr
->size_allocated
= size
;
1546 static inline void cstr_ccat(CString
*cstr
, int ch
)
1549 size
= cstr
->size
+ 1;
1550 if (size
> cstr
->size_allocated
)
1551 cstr_realloc(cstr
, size
);
1552 ((unsigned char *)cstr
->data
)[size
- 1] = ch
;
1556 static void cstr_cat(CString
*cstr
, const char *str
)
1568 /* add a wide char */
1569 static void cstr_wccat(CString
*cstr
, int ch
)
1572 size
= cstr
->size
+ sizeof(nwchar_t
);
1573 if (size
> cstr
->size_allocated
)
1574 cstr_realloc(cstr
, size
);
1575 *(nwchar_t
*)(((unsigned char *)cstr
->data
) + size
- sizeof(nwchar_t
)) = ch
;
1579 static void cstr_new(CString
*cstr
)
1581 memset(cstr
, 0, sizeof(CString
));
1584 /* free string and reset it to NULL */
1585 static void cstr_free(CString
*cstr
)
1587 tcc_free(cstr
->data_allocated
);
1591 #define cstr_reset(cstr) cstr_free(cstr)
1593 /* XXX: unicode ? */
1594 static void add_char(CString
*cstr
, int c
)
1596 if (c
== '\'' || c
== '\"' || c
== '\\') {
1597 /* XXX: could be more precise if char or string */
1598 cstr_ccat(cstr
, '\\');
1600 if (c
>= 32 && c
<= 126) {
1603 cstr_ccat(cstr
, '\\');
1605 cstr_ccat(cstr
, 'n');
1607 cstr_ccat(cstr
, '0' + ((c
>> 6) & 7));
1608 cstr_ccat(cstr
, '0' + ((c
>> 3) & 7));
1609 cstr_ccat(cstr
, '0' + (c
& 7));
1614 /* XXX: buffer overflow */
1615 /* XXX: float tokens */
1616 char *get_tok_str(int v
, CValue
*cv
)
1618 static char buf
[STRING_MAX_SIZE
+ 1];
1619 static CString cstr_buf
;
1625 /* NOTE: to go faster, we give a fixed buffer for small strings */
1626 cstr_reset(&cstr_buf
);
1627 cstr_buf
.data
= buf
;
1628 cstr_buf
.size_allocated
= sizeof(buf
);
1634 /* XXX: not quite exact, but only useful for testing */
1635 sprintf(p
, "%u", cv
->ui
);
1639 /* XXX: not quite exact, but only useful for testing */
1640 sprintf(p
, "%Lu", cv
->ull
);
1644 cstr_ccat(&cstr_buf
, '\'');
1645 add_char(&cstr_buf
, cv
->i
);
1646 cstr_ccat(&cstr_buf
, '\'');
1647 cstr_ccat(&cstr_buf
, '\0');
1651 len
= cstr
->size
- 1;
1653 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1654 cstr_ccat(&cstr_buf
, '\0');
1659 cstr_ccat(&cstr_buf
, '\"');
1661 len
= cstr
->size
- 1;
1663 add_char(&cstr_buf
, ((unsigned char *)cstr
->data
)[i
]);
1665 len
= (cstr
->size
/ sizeof(nwchar_t
)) - 1;
1667 add_char(&cstr_buf
, ((nwchar_t
*)cstr
->data
)[i
]);
1669 cstr_ccat(&cstr_buf
, '\"');
1670 cstr_ccat(&cstr_buf
, '\0');
1679 return strcpy(p
, "<<=");
1681 return strcpy(p
, ">>=");
1683 if (v
< TOK_IDENT
) {
1684 /* search in two bytes table */
1698 } else if (v
< tok_ident
) {
1699 return table_ident
[v
- TOK_IDENT
]->str
;
1700 } else if (v
>= SYM_FIRST_ANOM
) {
1701 /* special name for anonymous symbol */
1702 sprintf(p
, "L.%u", v
- SYM_FIRST_ANOM
);
1704 /* should never happen */
1709 return cstr_buf
.data
;
1712 /* push, without hashing */
1713 static Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
1727 /* find a symbol and return its associated structure. 's' is the top
1728 of the symbol stack */
1729 static Sym
*sym_find2(Sym
*s
, int v
)
1739 /* structure lookup */
1740 static inline Sym
*struct_find(int v
)
1743 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1745 return table_ident
[v
]->sym_struct
;
1748 /* find an identifier */
1749 static inline Sym
*sym_find(int v
)
1752 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
1754 return table_ident
[v
]->sym_identifier
;
1757 /* push a given symbol on the symbol stack */
1758 static Sym
*sym_push(int v
, CType
*type
, int r
, int c
)
1767 s
= sym_push2(ps
, v
, type
->t
, c
);
1768 s
->type
.ref
= type
->ref
;
1770 /* don't record fields or anonymous symbols */
1772 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1773 /* record symbol in token array */
1774 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1776 ps
= &ts
->sym_struct
;
1778 ps
= &ts
->sym_identifier
;
1785 /* push a global identifier */
1786 static Sym
*global_identifier_push(int v
, int t
, int c
)
1789 s
= sym_push2(&global_stack
, v
, t
, c
);
1790 /* don't record anonymous symbol */
1791 if (v
< SYM_FIRST_ANOM
) {
1792 ps
= &table_ident
[v
- TOK_IDENT
]->sym_identifier
;
1793 /* modify the top most local identifier, so that
1794 sym_identifier will point to 's' when popped */
1796 ps
= &(*ps
)->prev_tok
;
1803 /* pop symbols until top reaches 'b' */
1804 static void sym_pop(Sym
**ptop
, Sym
*b
)
1814 /* remove symbol in token array */
1816 if (!(v
& SYM_FIELD
) && (v
& ~SYM_STRUCT
) < SYM_FIRST_ANOM
) {
1817 ts
= table_ident
[(v
& ~SYM_STRUCT
) - TOK_IDENT
];
1819 ps
= &ts
->sym_struct
;
1821 ps
= &ts
->sym_identifier
;
1832 BufferedFile
*tcc_open(TCCState
*s1
, const char *filename
)
1838 fd
= open(filename
, O_RDONLY
| O_BINARY
);
1841 bf
= tcc_malloc(sizeof(BufferedFile
));
1847 bf
->buf_ptr
= bf
->buffer
;
1848 bf
->buf_end
= bf
->buffer
;
1849 bf
->buffer
[0] = CH_EOB
; /* put eob symbol */
1850 pstrcpy(bf
->filename
, sizeof(bf
->filename
), filename
);
1851 len
= strlen(bf
->filename
);
1852 for (i
= 0; i
< len
; i
++)
1853 if (bf
->filename
[i
] == '\\')
1854 bf
->filename
[i
] = '/';
1856 bf
->ifndef_macro
= 0;
1857 bf
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
1858 // printf("opening '%s'\n", filename);
1862 void tcc_close(BufferedFile
*bf
)
1864 total_lines
+= bf
->line_num
;
1869 /* fill input buffer and peek next char */
1870 static int tcc_peekc_slow(BufferedFile
*bf
)
1873 /* only tries to read if really end of buffer */
1874 if (bf
->buf_ptr
>= bf
->buf_end
) {
1876 #if defined(PARSE_DEBUG)
1881 len
= read(bf
->fd
, bf
->buffer
, len
);
1888 bf
->buf_ptr
= bf
->buffer
;
1889 bf
->buf_end
= bf
->buffer
+ len
;
1890 *bf
->buf_end
= CH_EOB
;
1892 if (bf
->buf_ptr
< bf
->buf_end
) {
1893 return bf
->buf_ptr
[0];
1895 bf
->buf_ptr
= bf
->buf_end
;
1900 /* return the current character, handling end of block if necessary
1902 static int handle_eob(void)
1904 return tcc_peekc_slow(file
);
1907 /* read next char from current input file and handle end of input buffer */
1908 static inline void inp(void)
1910 ch
= *(++(file
->buf_ptr
));
1911 /* end of buffer/file handling */
1916 /* handle '\[\r]\n' */
1917 static void handle_stray(void)
1919 while (ch
== '\\') {
1924 } else if (ch
== '\r') {
1932 error("stray '\\' in program");
1937 /* skip the stray and handle the \\n case. Output an error if
1938 incorrect char after the stray */
1939 static int handle_stray1(uint8_t *p
)
1943 if (p
>= file
->buf_end
) {
1960 /* handle just the EOB case, but not stray */
1961 #define PEEKC_EOB(c, p)\
1972 /* handle the complicated stray case */
1973 #define PEEKC(c, p)\
1978 c = handle_stray1(p);\
1983 /* input with '\[\r]\n' handling. Note that this function cannot
1984 handle other characters after '\', so you cannot call it inside
1985 strings or comments */
1986 static void minp(void)
1994 /* single line C++ comments */
1995 static uint8_t *parse_line_comment(uint8_t *p
)
2003 if (c
== '\n' || c
== CH_EOF
) {
2005 } else if (c
== '\\') {
2014 } else if (c
== '\r') {
2032 static uint8_t *parse_comment(uint8_t *p
)
2038 /* fast skip loop */
2041 if (c
== '\n' || c
== '*' || c
== '\\')
2045 if (c
== '\n' || c
== '*' || c
== '\\')
2049 /* now we can handle all the cases */
2053 } else if (c
== '*') {
2059 } else if (c
== '/') {
2060 goto end_of_comment
;
2061 } else if (c
== '\\') {
2066 /* skip '\[\r]\n', otherwise just skip the stray */
2072 } else if (c
== '\r') {
2089 /* stray, eob or eof */
2094 error("unexpected end of file in comment");
2095 } else if (c
== '\\') {
2107 /* space exlcuding newline */
2108 static inline int is_space(int ch
)
2110 return ch
== ' ' || ch
== '\t' || ch
== '\v' || ch
== '\f' || ch
== '\r';
2113 static inline void skip_spaces(void)
2115 while (is_space(ch
))
2119 /* parse a string without interpreting escapes */
2120 static uint8_t *parse_pp_string(uint8_t *p
,
2121 int sep
, CString
*str
)
2129 } else if (c
== '\\') {
2134 unterminated_string
:
2135 /* XXX: indicate line number of start of string */
2136 error("missing terminating %c character", sep
);
2137 } else if (c
== '\\') {
2138 /* escape : just skip \[\r]\n */
2143 } else if (c
== '\r') {
2146 expect("'\n' after '\r'");
2149 } else if (c
== CH_EOF
) {
2150 goto unterminated_string
;
2153 cstr_ccat(str
, '\\');
2159 } else if (c
== '\n') {
2162 } else if (c
== '\r') {
2166 cstr_ccat(str
, '\r');
2182 /* skip block of text until #else, #elif or #endif. skip also pairs of
2184 void preprocess_skip(void)
2186 int a
, start_of_line
, c
;
2213 } else if (c
== '\\') {
2214 /* XXX: incorrect: should not give an error */
2215 ch
= file
->buf_ptr
[0];
2223 p
= parse_pp_string(p
, c
, NULL
);
2232 p
= parse_comment(p
);
2233 } else if (ch
== '/') {
2234 p
= parse_line_comment(p
);
2240 if (start_of_line
) {
2245 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
2247 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
2249 else if (tok
== TOK_ENDIF
)
2263 /* ParseState handling */
2265 /* XXX: currently, no include file info is stored. Thus, we cannot display
2266 accurate messages if the function or data definition spans multiple
2269 /* save current parse state in 's' */
2270 void save_parse_state(ParseState
*s
)
2272 s
->line_num
= file
->line_num
;
2273 s
->macro_ptr
= macro_ptr
;
2278 /* restore parse state from 's' */
2279 void restore_parse_state(ParseState
*s
)
2281 file
->line_num
= s
->line_num
;
2282 macro_ptr
= s
->macro_ptr
;
2287 /* return the number of additional 'ints' necessary to store the
2289 static inline int tok_ext_size(int t
)
2303 error("unsupported token");
2310 return LDOUBLE_SIZE
/ 4;
2316 /* token string handling */
2318 static inline void tok_str_new(TokenString
*s
)
2322 s
->allocated_len
= 0;
2323 s
->last_line_num
= -1;
2326 static void tok_str_free(int *str
)
2331 static int *tok_str_realloc(TokenString
*s
)
2335 if (s
->allocated_len
== 0) {
2338 len
= s
->allocated_len
* 2;
2340 str
= tcc_realloc(s
->str
, len
* sizeof(int));
2342 error("memory full");
2343 s
->allocated_len
= len
;
2348 static void tok_str_add(TokenString
*s
, int t
)
2354 if (len
>= s
->allocated_len
)
2355 str
= tok_str_realloc(s
);
2360 static void tok_str_add2(TokenString
*s
, int t
, CValue
*cv
)
2367 /* allocate space for worst case */
2368 if (len
+ TOK_MAX_SIZE
> s
->allocated_len
)
2369 str
= tok_str_realloc(s
);
2378 str
[len
++] = cv
->tab
[0];
2387 nb_words
= (sizeof(CString
) + cv
->cstr
->size
+ 3) >> 2;
2388 while ((len
+ nb_words
) > s
->allocated_len
)
2389 str
= tok_str_realloc(s
);
2390 cstr
= (CString
*)(str
+ len
);
2392 cstr
->size
= cv
->cstr
->size
;
2393 cstr
->data_allocated
= NULL
;
2394 cstr
->size_allocated
= cstr
->size
;
2395 memcpy((char *)cstr
+ sizeof(CString
),
2396 cv
->cstr
->data
, cstr
->size
);
2403 #if LDOUBLE_SIZE == 8
2406 str
[len
++] = cv
->tab
[0];
2407 str
[len
++] = cv
->tab
[1];
2409 #if LDOUBLE_SIZE == 12
2411 str
[len
++] = cv
->tab
[0];
2412 str
[len
++] = cv
->tab
[1];
2413 str
[len
++] = cv
->tab
[2];
2414 #elif LDOUBLE_SIZE != 8
2415 #error add long double size support
2424 /* add the current parse token in token string 's' */
2425 static void tok_str_add_tok(TokenString
*s
)
2429 /* save line number info */
2430 if (file
->line_num
!= s
->last_line_num
) {
2431 s
->last_line_num
= file
->line_num
;
2432 cval
.i
= s
->last_line_num
;
2433 tok_str_add2(s
, TOK_LINENUM
, &cval
);
2435 tok_str_add2(s
, tok
, &tokc
);
2438 #if LDOUBLE_SIZE == 12
2439 #define LDOUBLE_GET(p, cv) \
2443 #elif LDOUBLE_SIZE == 8
2444 #define LDOUBLE_GET(p, cv) \
2448 #error add long double size support
2452 /* get a token from an integer array and increment pointer
2453 accordingly. we code it as a macro to avoid pointer aliasing. */
2454 #define TOK_GET(t, p, cv) \
2469 cv.cstr = (CString *)p; \
2470 cv.cstr->data = (char *)p + sizeof(CString);\
2471 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2480 case TOK_CLDOUBLE: \
2481 LDOUBLE_GET(p, cv); \
2482 p += LDOUBLE_SIZE / 4; \
2489 /* defines handling */
2490 static inline void define_push(int v
, int macro_type
, int *str
, Sym
*first_arg
)
2494 s
= sym_push2(&define_stack
, v
, macro_type
, (int)str
);
2495 s
->next
= first_arg
;
2496 table_ident
[v
- TOK_IDENT
]->sym_define
= s
;
2499 /* undefined a define symbol. Its name is just set to zero */
2500 static void define_undef(Sym
*s
)
2504 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2505 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2509 static inline Sym
*define_find(int v
)
2512 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2514 return table_ident
[v
]->sym_define
;
2517 /* free define stack until top reaches 'b' */
2518 static void free_defines(Sym
*b
)
2526 /* do not free args or predefined defines */
2528 tok_str_free((int *)top
->c
);
2530 if (v
>= TOK_IDENT
&& v
< tok_ident
)
2531 table_ident
[v
- TOK_IDENT
]->sym_define
= NULL
;
2539 static Sym
*label_find(int v
)
2542 if ((unsigned)v
>= (unsigned)(tok_ident
- TOK_IDENT
))
2544 return table_ident
[v
]->sym_label
;
2547 static Sym
*label_push(Sym
**ptop
, int v
, int flags
)
2550 s
= sym_push2(ptop
, v
, 0, 0);
2552 ps
= &table_ident
[v
- TOK_IDENT
]->sym_label
;
2553 if (ptop
== &global_label_stack
) {
2554 /* modify the top most local identifier, so that
2555 sym_identifier will point to 's' when popped */
2557 ps
= &(*ps
)->prev_tok
;
2564 /* pop labels until element last is reached. Look if any labels are
2565 undefined. Define symbols if '&&label' was used. */
2566 static void label_pop(Sym
**ptop
, Sym
*slast
)
2569 for(s
= *ptop
; s
!= slast
; s
= s1
) {
2571 if (s
->r
== LABEL_DECLARED
) {
2572 warning("label '%s' declared but not used", get_tok_str(s
->v
, NULL
));
2573 } else if (s
->r
== LABEL_FORWARD
) {
2574 error("label '%s' used but not defined",
2575 get_tok_str(s
->v
, NULL
));
2578 /* define corresponding symbol. A size of
2580 put_extern_sym(s
, cur_text_section
, (long)s
->next
, 1);
2584 table_ident
[s
->v
- TOK_IDENT
]->sym_label
= s
->prev_tok
;
2590 /* eval an expression for #if/#elif */
2591 static int expr_preprocess(void)
2597 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2598 next(); /* do macro subst */
2599 if (tok
== TOK_DEFINED
) {
2604 c
= define_find(tok
) != 0;
2609 } else if (tok
>= TOK_IDENT
) {
2610 /* if undefined macro */
2614 tok_str_add_tok(&str
);
2616 tok_str_add(&str
, -1); /* simulate end of file */
2617 tok_str_add(&str
, 0);
2618 /* now evaluate C constant expression */
2619 macro_ptr
= str
.str
;
2623 tok_str_free(str
.str
);
2627 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
2628 static void tok_print(int *str
)
2634 TOK_GET(t
, str
, cval
);
2637 printf(" %s", get_tok_str(t
, &cval
));
2643 /* parse after #define */
2644 static void parse_define(void)
2646 Sym
*s
, *first
, **ps
;
2647 int v
, t
, varg
, is_vaargs
, c
;
2652 error("invalid macro name '%s'", get_tok_str(tok
, &tokc
));
2653 /* XXX: should check if same macro (ANSI) */
2656 /* '(' must be just after macro definition for MACRO_FUNC */
2657 c
= file
->buf_ptr
[0];
2659 c
= handle_stray1(file
->buf_ptr
);
2664 while (tok
!= ')') {
2668 if (varg
== TOK_DOTS
) {
2669 varg
= TOK___VA_ARGS__
;
2671 } else if (tok
== TOK_DOTS
&& gnu_ext
) {
2675 if (varg
< TOK_IDENT
)
2676 error("badly punctuated parameter list");
2677 s
= sym_push2(&define_stack
, varg
| SYM_FIELD
, is_vaargs
, 0);
2688 /* EOF testing necessary for '-D' handling */
2689 while (tok
!= TOK_LINEFEED
&& tok
!= TOK_EOF
) {
2690 tok_str_add2(&str
, tok
, &tokc
);
2693 tok_str_add(&str
, 0);
2695 printf("define %s %d: ", get_tok_str(v
, NULL
), t
);
2698 define_push(v
, t
, str
.str
, first
);
2701 static inline int hash_cached_include(int type
, const char *filename
)
2703 const unsigned char *s
;
2707 h
= TOK_HASH_FUNC(h
, type
);
2710 h
= TOK_HASH_FUNC(h
, *s
);
2713 h
&= (CACHED_INCLUDES_HASH_SIZE
- 1);
2717 /* XXX: use a token or a hash table to accelerate matching ? */
2718 static CachedInclude
*search_cached_include(TCCState
*s1
,
2719 int type
, const char *filename
)
2723 h
= hash_cached_include(type
, filename
);
2724 i
= s1
->cached_includes_hash
[h
];
2728 e
= s1
->cached_includes
[i
- 1];
2729 if (e
->type
== type
&& !strcmp(e
->filename
, filename
))
2736 static inline void add_cached_include(TCCState
*s1
, int type
,
2737 const char *filename
, int ifndef_macro
)
2742 if (search_cached_include(s1
, type
, filename
))
2745 printf("adding cached '%s' %s\n", filename
, get_tok_str(ifndef_macro
, NULL
));
2747 e
= tcc_malloc(sizeof(CachedInclude
) + strlen(filename
));
2751 strcpy(e
->filename
, filename
);
2752 e
->ifndef_macro
= ifndef_macro
;
2753 dynarray_add((void ***)&s1
->cached_includes
, &s1
->nb_cached_includes
, e
);
2754 /* add in hash table */
2755 h
= hash_cached_include(type
, filename
);
2756 e
->hash_next
= s1
->cached_includes_hash
[h
];
2757 s1
->cached_includes_hash
[h
] = s1
->nb_cached_includes
;
2760 static void pragma_parse(TCCState
*s1
)
2765 if (tok
== TOK_pack
) {
2768 #pragma pack(1) // set
2769 #pragma pack() // reset to default
2770 #pragma pack(push,1) // push & set
2771 #pragma pack(pop) // restore previous
2775 if (tok
== TOK_ASM_pop
) {
2777 if (s1
->pack_stack_ptr
<= s1
->pack_stack
) {
2779 error("out of pack stack");
2781 s1
->pack_stack_ptr
--;
2785 if (tok
== TOK_ASM_push
) {
2787 if (s1
->pack_stack_ptr
>= s1
->pack_stack
+ PACK_STACK_SIZE
- 1)
2789 s1
->pack_stack_ptr
++;
2792 if (tok
!= TOK_CINT
) {
2794 error("invalid pack pragma");
2797 if (val
< 1 || val
> 16 || (val
& (val
- 1)) != 0)
2801 *s1
->pack_stack_ptr
= val
;
2807 /* is_bof is true if first non space token at beginning of file */
2808 static void preprocess(int is_bof
)
2810 TCCState
*s1
= tcc_state
;
2811 int size
, i
, c
, n
, saved_parse_flags
;
2812 char buf
[1024], *q
, *p
;
2818 saved_parse_flags
= parse_flags
;
2819 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
|
2820 PARSE_FLAG_LINEFEED
;
2830 s
= define_find(tok
);
2831 /* undefine symbol by putting an invalid name */
2836 case TOK_INCLUDE_NEXT
:
2837 ch
= file
->buf_ptr
[0];
2838 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2843 } else if (ch
== '\"') {
2846 /* XXX: better stray handling */
2849 while (ch
!= c
&& ch
!= '\n' && ch
!= CH_EOF
) {
2850 if ((q
- buf
) < sizeof(buf
) - 1)
2857 /* eat all spaces and comments after include */
2858 /* XXX: slightly incorrect */
2859 while (ch1
!= '\n' && ch1
!= CH_EOF
)
2863 /* computed #include : either we have only strings or
2864 we have anything enclosed in '<>' */
2867 if (tok
== TOK_STR
) {
2868 while (tok
!= TOK_LINEFEED
) {
2869 if (tok
!= TOK_STR
) {
2871 error("'#include' expects \"FILENAME\" or <FILENAME>");
2873 pstrcat(buf
, sizeof(buf
), (char *)tokc
.cstr
->data
);
2879 while (tok
!= TOK_LINEFEED
) {
2880 pstrcat(buf
, sizeof(buf
), get_tok_str(tok
, &tokc
));
2884 /* check syntax and remove '<>' */
2885 if (len
< 2 || buf
[0] != '<' || buf
[len
- 1] != '>')
2886 goto include_syntax
;
2887 memmove(buf
, buf
+ 1, len
- 2);
2888 buf
[len
- 2] = '\0';
2893 e
= search_cached_include(s1
, c
, buf
);
2894 if (e
&& define_find(e
->ifndef_macro
)) {
2895 /* no need to parse the include because the 'ifndef macro'
2898 printf("%s: skipping %s\n", file
->filename
, buf
);
2902 /* first search in current dir if "header.h" */
2904 p
= strrchr(file
->filename
, '/');
2906 size
= p
+ 1 - file
->filename
;
2907 if (size
> sizeof(buf1
) - 1)
2908 size
= sizeof(buf1
) - 1;
2909 memcpy(buf1
, file
->filename
, size
);
2911 pstrcat(buf1
, sizeof(buf1
), buf
);
2912 f
= tcc_open(s1
, buf1
);
2914 if (tok
== TOK_INCLUDE_NEXT
)
2920 if (s1
->include_stack_ptr
>= s1
->include_stack
+ INCLUDE_STACK_SIZE
)
2921 error("#include recursion too deep");
2922 /* now search in all the include paths */
2923 n
= s1
->nb_include_paths
+ s1
->nb_sysinclude_paths
;
2924 for(i
= 0; i
< n
; i
++) {
2926 if (i
< s1
->nb_include_paths
)
2927 path
= s1
->include_paths
[i
];
2929 path
= s1
->sysinclude_paths
[i
- s1
->nb_include_paths
];
2930 pstrcpy(buf1
, sizeof(buf1
), path
);
2931 pstrcat(buf1
, sizeof(buf1
), "/");
2932 pstrcat(buf1
, sizeof(buf1
), buf
);
2933 f
= tcc_open(s1
, buf1
);
2935 if (tok
== TOK_INCLUDE_NEXT
)
2941 error("include file '%s' not found", buf
);
2945 printf("%s: including %s\n", file
->filename
, buf1
);
2948 pstrcpy(f
->inc_filename
, sizeof(f
->inc_filename
), buf
);
2949 /* push current file in stack */
2950 /* XXX: fix current line init */
2951 *s1
->include_stack_ptr
++ = file
;
2953 /* add include file debug info */
2955 put_stabs(file
->filename
, N_BINCL
, 0, 0, 0);
2957 tok_flags
|= TOK_FLAG_BOF
| TOK_FLAG_BOL
;
2958 ch
= file
->buf_ptr
[0];
2966 c
= expr_preprocess();
2972 if (tok
< TOK_IDENT
)
2973 error("invalid argument for '#if%sdef'", c
? "n" : "");
2977 printf("#ifndef %s\n", get_tok_str(tok
, NULL
));
2979 file
->ifndef_macro
= tok
;
2982 c
= (define_find(tok
) != 0) ^ c
;
2984 if (s1
->ifdef_stack_ptr
>= s1
->ifdef_stack
+ IFDEF_STACK_SIZE
)
2985 error("memory full");
2986 *s1
->ifdef_stack_ptr
++ = c
;
2989 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
2990 error("#else without matching #if");
2991 if (s1
->ifdef_stack_ptr
[-1] & 2)
2992 error("#else after #else");
2993 c
= (s1
->ifdef_stack_ptr
[-1] ^= 3);
2996 if (s1
->ifdef_stack_ptr
== s1
->ifdef_stack
)
2997 error("#elif without matching #if");
2998 c
= s1
->ifdef_stack_ptr
[-1];
3000 error("#elif after #else");
3001 /* last #if/#elif expression was true: we skip */
3004 c
= expr_preprocess();
3005 s1
->ifdef_stack_ptr
[-1] = c
;
3015 if (s1
->ifdef_stack_ptr
<= file
->ifdef_stack_ptr
)
3016 error("#endif without matching #if");
3017 s1
->ifdef_stack_ptr
--;
3018 /* '#ifndef macro' was at the start of file. Now we check if
3019 an '#endif' is exactly at the end of file */
3020 if (file
->ifndef_macro
&&
3021 s1
->ifdef_stack_ptr
== file
->ifdef_stack_ptr
) {
3022 file
->ifndef_macro_saved
= file
->ifndef_macro
;
3023 /* need to set to zero to avoid false matches if another
3024 #ifndef at middle of file */
3025 file
->ifndef_macro
= 0;
3026 while (tok
!= TOK_LINEFEED
)
3028 tok_flags
|= TOK_FLAG_ENDIF
;
3034 if (tok
!= TOK_CINT
)
3036 file
->line_num
= tokc
.i
- 1; /* the line number will be incremented after */
3038 if (tok
!= TOK_LINEFEED
) {
3041 pstrcpy(file
->filename
, sizeof(file
->filename
),
3042 (char *)tokc
.cstr
->data
);
3048 ch
= file
->buf_ptr
[0];
3051 while (ch
!= '\n' && ch
!= CH_EOF
) {
3052 if ((q
- buf
) < sizeof(buf
) - 1)
3058 error("#error %s", buf
);
3060 warning("#warning %s", buf
);
3066 if (tok
== TOK_LINEFEED
|| tok
== '!' || tok
== TOK_CINT
) {
3067 /* '!' is ignored to allow C scripts. numbers are ignored
3068 to emulate cpp behaviour */
3070 if (!(saved_parse_flags
& PARSE_FLAG_ASM_COMMENTS
))
3071 error("invalid preprocessing directive #%s", get_tok_str(tok
, &tokc
));
3075 /* ignore other preprocess commands or #! for C scripts */
3076 while (tok
!= TOK_LINEFEED
)
3079 parse_flags
= saved_parse_flags
;
3082 /* evaluate escape codes in a string. */
3083 static void parse_escape_string(CString
*outstr
, const uint8_t *buf
, int is_long
)
3098 case '0': case '1': case '2': case '3':
3099 case '4': case '5': case '6': case '7':
3100 /* at most three octal digits */
3105 n
= n
* 8 + c
- '0';
3109 n
= n
* 8 + c
- '0';
3114 goto add_char_nonext
;
3120 if (c
>= 'a' && c
<= 'f')
3122 else if (c
>= 'A' && c
<= 'F')
3132 goto add_char_nonext
;
3156 goto invalid_escape
;
3166 if (c
>= '!' && c
<= '~')
3167 warning("unknown escape sequence: \'\\%c\'", c
);
3169 warning("unknown escape sequence: \'\\x%x\'", c
);
3176 cstr_ccat(outstr
, c
);
3178 cstr_wccat(outstr
, c
);
3180 /* add a trailing '\0' */
3182 cstr_ccat(outstr
, '\0');
3184 cstr_wccat(outstr
, '\0');
3187 /* we use 64 bit numbers */
3190 /* bn = (bn << shift) | or_val */
3191 void bn_lshift(unsigned int *bn
, int shift
, int or_val
)
3195 for(i
=0;i
<BN_SIZE
;i
++) {
3197 bn
[i
] = (v
<< shift
) | or_val
;
3198 or_val
= v
>> (32 - shift
);
3202 void bn_zero(unsigned int *bn
)
3205 for(i
=0;i
<BN_SIZE
;i
++) {
3210 /* parse number in null terminated string 'p' and return it in the
3212 void parse_number(const char *p
)
3214 int b
, t
, shift
, frac_bits
, s
, exp_val
, ch
;
3216 unsigned int bn
[BN_SIZE
];
3227 goto float_frac_parse
;
3228 } else if (t
== '0') {
3229 if (ch
== 'x' || ch
== 'X') {
3233 } else if (tcc_ext
&& (ch
== 'b' || ch
== 'B')) {
3239 /* parse all digits. cannot check octal numbers at this stage
3240 because of floating point constants */
3242 if (ch
>= 'a' && ch
<= 'f')
3244 else if (ch
>= 'A' && ch
<= 'F')
3252 if (q
>= token_buf
+ STRING_MAX_SIZE
) {
3254 error("number too long");
3260 ((ch
== 'e' || ch
== 'E') && b
== 10) ||
3261 ((ch
== 'p' || ch
== 'P') && (b
== 16 || b
== 2))) {
3263 /* NOTE: strtox should support that for hexa numbers, but
3264 non ISOC99 libcs do not support it, so we prefer to do
3266 /* hexadecimal or binary floats */
3267 /* XXX: handle overflows */
3279 } else if (t
>= 'a') {
3281 } else if (t
>= 'A') {
3286 bn_lshift(bn
, shift
, t
);
3293 if (t
>= 'a' && t
<= 'f') {
3295 } else if (t
>= 'A' && t
<= 'F') {
3297 } else if (t
>= '0' && t
<= '9') {
3303 error("invalid digit");
3304 bn_lshift(bn
, shift
, t
);
3309 if (ch
!= 'p' && ch
!= 'P')
3316 } else if (ch
== '-') {
3320 if (ch
< '0' || ch
> '9')
3321 expect("exponent digits");
3322 while (ch
>= '0' && ch
<= '9') {
3323 exp_val
= exp_val
* 10 + ch
- '0';
3326 exp_val
= exp_val
* s
;
3328 /* now we can generate the number */
3329 /* XXX: should patch directly float number */
3330 d
= (double)bn
[1] * 4294967296.0 + (double)bn
[0];
3331 d
= ldexp(d
, exp_val
- frac_bits
);
3336 /* float : should handle overflow */
3338 } else if (t
== 'L') {
3341 /* XXX: not large enough */
3342 tokc
.ld
= (long double)d
;
3348 /* decimal floats */
3350 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3355 while (ch
>= '0' && ch
<= '9') {
3356 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3362 if (ch
== 'e' || ch
== 'E') {
3363 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3367 if (ch
== '-' || ch
== '+') {
3368 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3373 if (ch
< '0' || ch
> '9')
3374 expect("exponent digits");
3375 while (ch
>= '0' && ch
<= '9') {
3376 if (q
>= token_buf
+ STRING_MAX_SIZE
)
3388 tokc
.f
= strtof(token_buf
, NULL
);
3389 } else if (t
== 'L') {
3392 tokc
.ld
= strtold(token_buf
, NULL
);
3395 tokc
.d
= strtod(token_buf
, NULL
);
3399 unsigned long long n
, n1
;
3402 /* integer number */
3405 if (b
== 10 && *q
== '0') {
3412 /* no need for checks except for base 10 / 8 errors */
3415 } else if (t
>= 'a') {
3417 } else if (t
>= 'A') {
3422 error("invalid digit");
3426 /* detect overflow */
3427 /* XXX: this test is not reliable */
3429 error("integer constant overflow");
3432 /* XXX: not exactly ANSI compliant */
3433 if ((n
& 0xffffffff00000000LL
) != 0) {
3438 } else if (n
> 0x7fffffff) {
3449 error("three 'l's in integer constant");
3452 if (tok
== TOK_CINT
)
3454 else if (tok
== TOK_CUINT
)
3458 } else if (t
== 'U') {
3460 error("two 'u's in integer constant");
3462 if (tok
== TOK_CINT
)
3464 else if (tok
== TOK_CLLONG
)
3471 if (tok
== TOK_CINT
|| tok
== TOK_CUINT
)
3479 #define PARSE2(c1, tok1, c2, tok2) \
3490 /* return next token without macro substitution */
3491 static inline void next_nomacro1(void)
3511 /* first look if it is in fact an end of buffer */
3512 if (p
>= file
->buf_end
) {
3516 if (p
>= file
->buf_end
)
3529 TCCState
*s1
= tcc_state
;
3530 if (parse_flags
& PARSE_FLAG_LINEFEED
) {
3532 } else if (s1
->include_stack_ptr
== s1
->include_stack
||
3533 !(parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3534 /* no include left : end of file. */
3537 /* pop include file */
3539 /* test if previous '#endif' was after a #ifdef at
3541 if (tok_flags
& TOK_FLAG_ENDIF
) {
3543 printf("#endif %s\n", get_tok_str(file
->ifndef_macro_saved
, NULL
));
3545 add_cached_include(s1
, file
->inc_type
, file
->inc_filename
,
3546 file
->ifndef_macro_saved
);
3549 /* add end of include file debug info */
3551 put_stabd(N_EINCL
, 0, 0);
3553 /* pop include stack */
3555 s1
->include_stack_ptr
--;
3556 file
= *s1
->include_stack_ptr
;
3564 if (parse_flags
& PARSE_FLAG_LINEFEED
) {
3568 tok_flags
|= TOK_FLAG_BOL
;
3577 if ((tok_flags
& TOK_FLAG_BOL
) &&
3578 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
3580 preprocess(tok_flags
& TOK_FLAG_BOF
);
3586 tok
= TOK_TWOSHARPS
;
3588 if (parse_flags
& PARSE_FLAG_ASM_COMMENTS
) {
3589 p
= parse_line_comment(p
- 1);
3598 case 'a': case 'b': case 'c': case 'd':
3599 case 'e': case 'f': case 'g': case 'h':
3600 case 'i': case 'j': case 'k': case 'l':
3601 case 'm': case 'n': case 'o': case 'p':
3602 case 'q': case 'r': case 's': case 't':
3603 case 'u': case 'v': case 'w': case 'x':
3605 case 'A': case 'B': case 'C': case 'D':
3606 case 'E': case 'F': case 'G': case 'H':
3607 case 'I': case 'J': case 'K':
3608 case 'M': case 'N': case 'O': case 'P':
3609 case 'Q': case 'R': case 'S': case 'T':
3610 case 'U': case 'V': case 'W': case 'X':
3616 h
= TOK_HASH_FUNC(h
, c
);
3620 if (!isidnum_table
[c
])
3622 h
= TOK_HASH_FUNC(h
, c
);
3629 /* fast case : no stray found, so we have the full token
3630 and we have already hashed it */
3632 h
&= (TOK_HASH_SIZE
- 1);
3633 pts
= &hash_ident
[h
];
3638 if (ts
->len
== len
&& !memcmp(ts
->str
, p1
, len
))
3640 pts
= &(ts
->hash_next
);
3642 ts
= tok_alloc_new(pts
, p1
, len
);
3646 cstr_reset(&tokcstr
);
3649 cstr_ccat(&tokcstr
, *p1
);
3655 while (isidnum_table
[c
]) {
3656 cstr_ccat(&tokcstr
, c
);
3659 ts
= tok_alloc(tokcstr
.data
, tokcstr
.size
);
3665 if (t
!= '\\' && t
!= '\'' && t
!= '\"') {
3667 goto parse_ident_fast
;
3670 if (c
== '\'' || c
== '\"') {
3674 cstr_reset(&tokcstr
);
3675 cstr_ccat(&tokcstr
, 'L');
3676 goto parse_ident_slow
;
3680 case '0': case '1': case '2': case '3':
3681 case '4': case '5': case '6': case '7':
3684 cstr_reset(&tokcstr
);
3685 /* after the first digit, accept digits, alpha, '.' or sign if
3686 prefixed by 'eEpP' */
3690 cstr_ccat(&tokcstr
, c
);
3692 if (!(isnum(c
) || isid(c
) || c
== '.' ||
3693 ((c
== '+' || c
== '-') &&
3694 (t
== 'e' || t
== 'E' || t
== 'p' || t
== 'P'))))
3697 /* We add a trailing '\0' to ease parsing */
3698 cstr_ccat(&tokcstr
, '\0');
3699 tokc
.cstr
= &tokcstr
;
3703 /* special dot handling because it can also start a number */
3706 cstr_reset(&tokcstr
);
3707 cstr_ccat(&tokcstr
, '.');
3709 } else if (c
== '.') {
3729 /* parse the string */
3731 p
= parse_pp_string(p
, sep
, &str
);
3732 cstr_ccat(&str
, '\0');
3734 /* eval the escape (should be done as TOK_PPNUM) */
3735 cstr_reset(&tokcstr
);
3736 parse_escape_string(&tokcstr
, str
.data
, is_long
);
3741 /* XXX: make it portable */
3745 char_size
= sizeof(nwchar_t
);
3746 if (tokcstr
.size
<= char_size
)
3747 error("empty character constant");
3748 if (tokcstr
.size
> 2 * char_size
)
3749 warning("multi-character character constant");
3751 tokc
.i
= *(int8_t *)tokcstr
.data
;
3754 tokc
.i
= *(nwchar_t
*)tokcstr
.data
;
3758 tokc
.cstr
= &tokcstr
;
3772 } else if (c
== '<') {
3790 } else if (c
== '>') {
3808 } else if (c
== '=') {
3821 } else if (c
== '=') {
3834 } else if (c
== '=') {
3847 } else if (c
== '=') {
3850 } else if (c
== '>') {
3858 PARSE2('!', '!', '=', TOK_NE
)
3859 PARSE2('=', '=', '=', TOK_EQ
)
3860 PARSE2('*', '*', '=', TOK_A_MUL
)
3861 PARSE2('%', '%', '=', TOK_A_MOD
)
3862 PARSE2('^', '^', '=', TOK_A_XOR
)
3864 /* comments or operator */
3868 p
= parse_comment(p
);
3870 } else if (c
== '/') {
3871 p
= parse_line_comment(p
);
3873 } else if (c
== '=') {
3893 case '$': /* only used in assembler */
3894 case '@': /* dito */
3899 error("unrecognized character \\x%02x", c
);
3904 #if defined(PARSE_DEBUG)
3905 printf("token = %s\n", get_tok_str(tok
, &tokc
));
3909 /* return next token without macro substitution. Can read input from
3911 static void next_nomacro(void)
3917 TOK_GET(tok
, macro_ptr
, tokc
);
3918 if (tok
== TOK_LINENUM
) {
3919 file
->line_num
= tokc
.i
;
3928 /* substitute args in macro_str and return allocated string */
3929 static int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
3931 int *st
, last_tok
, t
, notfirst
;
3940 TOK_GET(t
, macro_str
, cval
);
3945 TOK_GET(t
, macro_str
, cval
);
3948 s
= sym_find2(args
, t
);
3955 cstr_ccat(&cstr
, ' ');
3956 TOK_GET(t
, st
, cval
);
3957 cstr_cat(&cstr
, get_tok_str(t
, &cval
));
3960 cstr_ccat(&cstr
, '\0');
3962 printf("stringize: %s\n", (char *)cstr
.data
);
3966 tok_str_add2(&str
, TOK_STR
, &cval
);
3969 tok_str_add2(&str
, t
, &cval
);
3971 } else if (t
>= TOK_IDENT
) {
3972 s
= sym_find2(args
, t
);
3975 /* if '##' is present before or after, no arg substitution */
3976 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
3977 /* special case for var arg macros : ## eats the
3978 ',' if empty VA_ARGS variable. */
3979 /* XXX: test of the ',' is not 100%
3980 reliable. should fix it to avoid security
3982 if (gnu_ext
&& s
->type
.t
&&
3983 last_tok
== TOK_TWOSHARPS
&&
3984 str
.len
>= 2 && str
.str
[str
.len
- 2] == ',') {
3986 /* suppress ',' '##' */
3989 /* suppress '##' and add variable */
3997 TOK_GET(t1
, st
, cval
);
4000 tok_str_add2(&str
, t1
, &cval
);
4004 /* NOTE: the stream cannot be read when macro
4005 substituing an argument */
4006 macro_subst(&str
, nested_list
, st
, NULL
);
4009 tok_str_add(&str
, t
);
4012 tok_str_add2(&str
, t
, &cval
);
4016 tok_str_add(&str
, 0);
4020 static char const ab_month_name
[12][4] =
4022 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4023 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4026 /* do macro substitution of current token with macro 's' and add
4027 result to (tok_str,tok_len). 'nested_list' is the list of all
4028 macros we got inside to avoid recursing. Return non zero if no
4029 substitution needs to be done */
4030 static int macro_subst_tok(TokenString
*tok_str
,
4031 Sym
**nested_list
, Sym
*s
, struct macro_level
**can_read_stream
)
4033 Sym
*args
, *sa
, *sa1
;
4034 int mstr_allocated
, parlevel
, *mstr
, t
, t1
;
4041 /* if symbol is a macro, prepare substitution */
4042 /* special macros */
4043 if (tok
== TOK___LINE__
) {
4044 snprintf(buf
, sizeof(buf
), "%d", file
->line_num
);
4048 } else if (tok
== TOK___FILE__
) {
4049 cstrval
= file
->filename
;
4051 } else if (tok
== TOK___DATE__
|| tok
== TOK___TIME__
) {
4056 tm
= localtime(&ti
);
4057 if (tok
== TOK___DATE__
) {
4058 snprintf(buf
, sizeof(buf
), "%s %2d %d",
4059 ab_month_name
[tm
->tm_mon
], tm
->tm_mday
, tm
->tm_year
+ 1900);
4061 snprintf(buf
, sizeof(buf
), "%02d:%02d:%02d",
4062 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
);
4069 cstr_cat(&cstr
, cstrval
);
4070 cstr_ccat(&cstr
, '\0');
4072 tok_str_add2(tok_str
, t1
, &cval
);
4077 if (s
->type
.t
== MACRO_FUNC
) {
4078 /* NOTE: we do not use next_nomacro to avoid eating the
4079 next token. XXX: find better solution */
4083 if (t
== 0 && can_read_stream
) {
4084 /* end of macro stream: we must look at the token
4085 after in the file */
4086 struct macro_level
*ml
= *can_read_stream
;
4092 *can_read_stream
= ml
-> prev
;
4097 /* XXX: incorrect with comments */
4098 ch
= file
->buf_ptr
[0];
4099 while (is_space(ch
) || ch
== '\n')
4103 if (t
!= '(') /* no macro subst */
4106 /* argument macro */
4111 /* NOTE: empty args are allowed, except if no args */
4113 /* handle '()' case */
4114 if (!args
&& !sa
&& tok
== ')')
4117 error("macro '%s' used with too many args",
4118 get_tok_str(s
->v
, 0));
4121 /* NOTE: non zero sa->t indicates VA_ARGS */
4122 while ((parlevel
> 0 ||
4124 (tok
!= ',' || sa
->type
.t
))) &&
4128 else if (tok
== ')')
4130 tok_str_add2(&str
, tok
, &tokc
);
4133 tok_str_add(&str
, 0);
4134 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, sa
->type
.t
, (int)str
.str
);
4137 /* special case for gcc var args: add an empty
4138 var arg argument if it is omitted */
4139 if (sa
&& sa
->type
.t
&& gnu_ext
)
4149 error("macro '%s' used with too few args",
4150 get_tok_str(s
->v
, 0));
4153 /* now subst each arg */
4154 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
4159 tok_str_free((int *)sa
->c
);
4165 sym_push2(nested_list
, s
->v
, 0, 0);
4166 macro_subst(tok_str
, nested_list
, mstr
, can_read_stream
);
4167 /* pop nested defined symbol */
4169 *nested_list
= sa1
->prev
;
4177 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4178 return the resulting string (which must be freed). */
4179 static inline int *macro_twosharps(const int *macro_str
)
4182 const int *macro_ptr1
, *start_macro_ptr
, *ptr
, *saved_macro_ptr
;
4184 const char *p1
, *p2
;
4186 TokenString macro_str1
;
4189 start_macro_ptr
= macro_str
;
4190 /* we search the first '##' */
4192 macro_ptr1
= macro_str
;
4193 TOK_GET(t
, macro_str
, cval
);
4194 /* nothing more to do if end of string */
4197 if (*macro_str
== TOK_TWOSHARPS
)
4201 /* we saw '##', so we need more processing to handle it */
4203 tok_str_new(¯o_str1
);
4207 /* add all tokens seen so far */
4208 for(ptr
= start_macro_ptr
; ptr
< macro_ptr1
;) {
4209 TOK_GET(t
, ptr
, cval
);
4210 tok_str_add2(¯o_str1
, t
, &cval
);
4212 saved_macro_ptr
= macro_ptr
;
4213 /* XXX: get rid of the use of macro_ptr here */
4214 macro_ptr
= (int *)macro_str
;
4216 while (*macro_ptr
== TOK_TWOSHARPS
) {
4218 macro_ptr1
= macro_ptr
;
4221 TOK_GET(t
, macro_ptr
, cval
);
4222 /* We concatenate the two tokens if we have an
4223 identifier or a preprocessing number */
4225 p1
= get_tok_str(tok
, &tokc
);
4226 cstr_cat(&cstr
, p1
);
4227 p2
= get_tok_str(t
, &cval
);
4228 cstr_cat(&cstr
, p2
);
4229 cstr_ccat(&cstr
, '\0');
4231 if ((tok
>= TOK_IDENT
|| tok
== TOK_PPNUM
) &&
4232 (t
>= TOK_IDENT
|| t
== TOK_PPNUM
)) {
4233 if (tok
== TOK_PPNUM
) {
4234 /* if number, then create a number token */
4235 /* NOTE: no need to allocate because
4236 tok_str_add2() does it */
4239 /* if identifier, we must do a test to
4240 validate we have a correct identifier */
4241 if (t
== TOK_PPNUM
) {
4251 if (!isnum(c
) && !isid(c
))
4255 ts
= tok_alloc(cstr
.data
, strlen(cstr
.data
));
4256 tok
= ts
->tok
; /* modify current token */
4259 const char *str
= cstr
.data
;
4260 const unsigned char *q
;
4262 /* we look for a valid token */
4263 /* XXX: do more extensive checks */
4264 if (!strcmp(str
, ">>=")) {
4266 } else if (!strcmp(str
, "<<=")) {
4268 } else if (strlen(str
) == 2) {
4269 /* search in two bytes table */
4274 if (q
[0] == str
[0] && q
[1] == str
[1])
4281 /* NOTE: because get_tok_str use a static buffer,
4284 p1
= get_tok_str(tok
, &tokc
);
4285 cstr_cat(&cstr
, p1
);
4286 cstr_ccat(&cstr
, '\0');
4287 p2
= get_tok_str(t
, &cval
);
4288 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr
.data
, p2
);
4289 /* cannot merge tokens: just add them separately */
4290 tok_str_add2(¯o_str1
, tok
, &tokc
);
4291 /* XXX: free associated memory ? */
4298 tok_str_add2(¯o_str1
, tok
, &tokc
);
4303 macro_ptr
= (int *)saved_macro_ptr
;
4305 tok_str_add(¯o_str1
, 0);
4306 return macro_str1
.str
;
4310 /* do macro substitution of macro_str and add result to
4311 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4312 inside to avoid recursing. */
4313 static void macro_subst(TokenString
*tok_str
, Sym
**nested_list
,
4314 const int *macro_str
, struct macro_level
** can_read_stream
)
4321 struct macro_level ml
;
4323 /* first scan for '##' operator handling */
4325 macro_str1
= macro_twosharps(ptr
);
4329 /* NOTE: ptr == NULL can only happen if tokens are read from
4330 file stream due to a macro function call */
4333 TOK_GET(t
, ptr
, cval
);
4338 /* if nested substitution, do nothing */
4339 if (sym_find2(*nested_list
, t
))
4342 if (can_read_stream
)
4343 ml
.prev
= *can_read_stream
, *can_read_stream
= &ml
;
4344 macro_ptr
= (int *)ptr
;
4346 ret
= macro_subst_tok(tok_str
, nested_list
, s
, can_read_stream
);
4347 ptr
= (int *)macro_ptr
;
4349 if (can_read_stream
&& *can_read_stream
== &ml
)
4350 *can_read_stream
= ml
.prev
;
4355 tok_str_add2(tok_str
, t
, &cval
);
4359 tok_str_free(macro_str1
);
4362 /* return next token with macro substitution */
4363 static void next(void)
4365 Sym
*nested_list
, *s
;
4367 struct macro_level
*ml
;
4372 /* if not reading from macro substituted string, then try
4373 to substitute macros */
4374 if (tok
>= TOK_IDENT
&&
4375 (parse_flags
& PARSE_FLAG_PREPROCESS
)) {
4376 s
= define_find(tok
);
4378 /* we have a macro: we try to substitute */
4382 if (macro_subst_tok(&str
, &nested_list
, s
, &ml
) == 0) {
4383 /* substitution done, NOTE: maybe empty */
4384 tok_str_add(&str
, 0);
4385 macro_ptr
= str
.str
;
4386 macro_ptr_allocated
= str
.str
;
4393 /* end of macro or end of unget buffer */
4394 if (unget_buffer_enabled
) {
4395 macro_ptr
= unget_saved_macro_ptr
;
4396 unget_buffer_enabled
= 0;
4398 /* end of macro string: free it */
4399 tok_str_free(macro_ptr_allocated
);
4406 /* convert preprocessor tokens into C tokens */
4407 if (tok
== TOK_PPNUM
&&
4408 (parse_flags
& PARSE_FLAG_TOK_NUM
)) {
4409 parse_number((char *)tokc
.cstr
->data
);
4413 /* push back current token and set current token to 'last_tok'. Only
4414 identifier case handled for labels. */
4415 static inline void unget_tok(int last_tok
)
4419 unget_saved_macro_ptr
= macro_ptr
;
4420 unget_buffer_enabled
= 1;
4421 q
= unget_saved_buffer
;
4424 n
= tok_ext_size(tok
) - 1;
4427 *q
= 0; /* end of token string */
4432 void swap(int *p
, int *q
)
4440 void vsetc(CType
*type
, int r
, CValue
*vc
)
4444 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4445 error("memory full");
4446 /* cannot let cpu flags if other instruction are generated. Also
4447 avoid leaving VT_JMP anywhere except on the top of the stack
4448 because it would complicate the code generator. */
4449 if (vtop
>= vstack
) {
4450 v
= vtop
->r
& VT_VALMASK
;
4451 if (v
== VT_CMP
|| (v
& ~1) == VT_JMP
)
4457 vtop
->r2
= VT_CONST
;
4461 /* push integer constant */
4466 vsetc(&int_type
, VT_CONST
, &cval
);
4469 /* Return a static symbol pointing to a section */
4470 static Sym
*get_sym_ref(CType
*type
, Section
*sec
,
4471 unsigned long offset
, unsigned long size
)
4477 sym
= global_identifier_push(v
, type
->t
| VT_STATIC
, 0);
4478 sym
->type
.ref
= type
->ref
;
4479 sym
->r
= VT_CONST
| VT_SYM
;
4480 put_extern_sym(sym
, sec
, offset
, size
);
4484 /* push a reference to a section offset by adding a dummy symbol */
4485 static void vpush_ref(CType
*type
, Section
*sec
, unsigned long offset
, unsigned long size
)
4490 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4491 vtop
->sym
= get_sym_ref(type
, sec
, offset
, size
);
4494 /* define a new external reference to a symbol 'v' of type 'u' */
4495 static Sym
*external_global_sym(int v
, CType
*type
, int r
)
4501 /* push forward reference */
4502 s
= global_identifier_push(v
, type
->t
| VT_EXTERN
, 0);
4503 s
->type
.ref
= type
->ref
;
4504 s
->r
= r
| VT_CONST
| VT_SYM
;
4509 /* define a new external reference to a symbol 'v' of type 'u' */
4510 static Sym
*external_sym(int v
, CType
*type
, int r
)
4516 /* push forward reference */
4517 s
= sym_push(v
, type
, r
| VT_CONST
| VT_SYM
, 0);
4518 s
->type
.t
|= VT_EXTERN
;
4520 if (!is_compatible_types(&s
->type
, type
))
4521 error("incompatible types for redefinition of '%s'",
4522 get_tok_str(v
, NULL
));
4527 /* push a reference to global symbol v */
4528 static void vpush_global_sym(CType
*type
, int v
)
4533 sym
= external_global_sym(v
, type
, 0);
4535 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
4539 void vset(CType
*type
, int r
, int v
)
4544 vsetc(type
, r
, &cval
);
4547 void vseti(int r
, int v
)
4563 void vpushv(SValue
*v
)
4565 if (vtop
>= vstack
+ (VSTACK_SIZE
- 1))
4566 error("memory full");
4576 /* save r to the memory stack, and mark it as being free */
4577 void save_reg(int r
)
4579 int l
, saved
, size
, align
;
4583 /* modify all stack values */
4586 for(p
=vstack
;p
<=vtop
;p
++) {
4587 if ((p
->r
& VT_VALMASK
) == r
||
4588 (p
->r2
& VT_VALMASK
) == r
) {
4589 /* must save value on stack if not already done */
4591 /* NOTE: must reload 'r' because r might be equal to r2 */
4592 r
= p
->r
& VT_VALMASK
;
4593 /* store register in the stack */
4595 if ((p
->r
& VT_LVAL
) ||
4596 (!is_float(type
->t
) && (type
->t
& VT_BTYPE
) != VT_LLONG
))
4598 size
= type_size(type
, &align
);
4599 loc
= (loc
- size
) & -align
;
4600 sv
.type
.t
= type
->t
;
4601 sv
.r
= VT_LOCAL
| VT_LVAL
;
4604 #ifdef TCC_TARGET_I386
4605 /* x86 specific: need to pop fp register ST0 if saved */
4606 if (r
== TREG_ST0
) {
4607 o(0xd9dd); /* fstp %st(1) */
4610 /* special long long case */
4611 if ((type
->t
& VT_BTYPE
) == VT_LLONG
) {
4618 /* mark that stack entry as being saved on the stack */
4619 if (p
->r
& VT_LVAL
) {
4620 /* also clear the bounded flag because the
4621 relocation address of the function was stored in
4623 p
->r
= (p
->r
& ~(VT_VALMASK
| VT_BOUNDED
)) | VT_LLOCAL
;
4625 p
->r
= lvalue_type(p
->type
.t
) | VT_LOCAL
;
4633 /* find a register of class 'rc2' with at most one reference on stack.
4634 * If none, call get_reg(rc) */
4635 int get_reg_ex(int rc
, int rc2
)
4640 for(r
=0;r
<NB_REGS
;r
++) {
4641 if (reg_classes
[r
] & rc2
) {
4644 for(p
= vstack
; p
<= vtop
; p
++) {
4645 if ((p
->r
& VT_VALMASK
) == r
||
4646 (p
->r2
& VT_VALMASK
) == r
)
4656 /* find a free register of class 'rc'. If none, save one register */
4662 /* find a free register */
4663 for(r
=0;r
<NB_REGS
;r
++) {
4664 if (reg_classes
[r
] & rc
) {
4665 for(p
=vstack
;p
<=vtop
;p
++) {
4666 if ((p
->r
& VT_VALMASK
) == r
||
4667 (p
->r2
& VT_VALMASK
) == r
)
4675 /* no register left : free the first one on the stack (VERY
4676 IMPORTANT to start from the bottom to ensure that we don't
4677 spill registers used in gen_opi()) */
4678 for(p
=vstack
;p
<=vtop
;p
++) {
4679 r
= p
->r
& VT_VALMASK
;
4680 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
))
4682 /* also look at second register (if long long) */
4683 r
= p
->r2
& VT_VALMASK
;
4684 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
4690 /* Should never comes here */
4694 /* save registers up to (vtop - n) stack entry */
4695 void save_regs(int n
)
4700 for(p
= vstack
;p
<= p1
; p
++) {
4701 r
= p
->r
& VT_VALMASK
;
4708 /* move register 's' to 'r', and flush previous value of r to memory
4710 void move_reg(int r
, int s
)
4723 /* get address of vtop (vtop MUST BE an lvalue) */
4726 vtop
->r
&= ~VT_LVAL
;
4727 /* tricky: if saved lvalue, then we can go back to lvalue */
4728 if ((vtop
->r
& VT_VALMASK
) == VT_LLOCAL
)
4729 vtop
->r
= (vtop
->r
& ~(VT_VALMASK
| VT_LVAL_TYPE
)) | VT_LOCAL
| VT_LVAL
;
4732 #ifdef CONFIG_TCC_BCHECK
4733 /* generate lvalue bound code */
4739 vtop
->r
&= ~VT_MUSTBOUND
;
4740 /* if lvalue, then use checking code before dereferencing */
4741 if (vtop
->r
& VT_LVAL
) {
4742 /* if not VT_BOUNDED value, then make one */
4743 if (!(vtop
->r
& VT_BOUNDED
)) {
4744 lval_type
= vtop
->r
& (VT_LVAL_TYPE
| VT_LVAL
);
4745 /* must save type because we must set it to int to get pointer */
4747 vtop
->type
.t
= VT_INT
;
4750 gen_bounded_ptr_add();
4751 vtop
->r
|= lval_type
;
4754 /* then check for dereferencing */
4755 gen_bounded_ptr_deref();
4760 /* store vtop a register belonging to class 'rc'. lvalues are
4761 converted to values. Cannot be used if cannot be converted to
4762 register value (such as structures). */
4765 int r
, r2
, rc2
, bit_pos
, bit_size
, size
, align
, i
;
4766 unsigned long long ll
;
4768 /* NOTE: get_reg can modify vstack[] */
4769 if (vtop
->type
.t
& VT_BITFIELD
) {
4770 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
4771 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
4772 /* remove bit field info to avoid loops */
4773 vtop
->type
.t
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
4774 /* generate shifts */
4775 vpushi(32 - (bit_pos
+ bit_size
));
4777 vpushi(32 - bit_size
);
4778 /* NOTE: transformed to SHR if unsigned */
4782 if (is_float(vtop
->type
.t
) &&
4783 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4786 unsigned long offset
;
4788 /* XXX: unify with initializers handling ? */
4789 /* CPUs usually cannot use float constants, so we store them
4790 generically in data segment */
4791 size
= type_size(&vtop
->type
, &align
);
4792 offset
= (data_section
->data_offset
+ align
- 1) & -align
;
4793 data_section
->data_offset
= offset
;
4794 /* XXX: not portable yet */
4795 ptr
= section_ptr_add(data_section
, size
);
4798 ptr
[i
] = vtop
->c
.tab
[i
];
4799 sym
= get_sym_ref(&vtop
->type
, data_section
, offset
, size
<< 2);
4800 vtop
->r
|= VT_LVAL
| VT_SYM
;
4804 #ifdef CONFIG_TCC_BCHECK
4805 if (vtop
->r
& VT_MUSTBOUND
)
4809 r
= vtop
->r
& VT_VALMASK
;
4810 /* need to reload if:
4812 - lvalue (need to dereference pointer)
4813 - already a register, but not in the right class */
4814 if (r
>= VT_CONST
||
4815 (vtop
->r
& VT_LVAL
) ||
4816 !(reg_classes
[r
] & rc
) ||
4817 ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
&&
4818 !(reg_classes
[vtop
->r2
] & rc
))) {
4820 if ((vtop
->type
.t
& VT_BTYPE
) == VT_LLONG
) {
4821 /* two register type load : expand to two words
4823 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
4826 vtop
->c
.ui
= ll
; /* first word */
4828 vtop
->r
= r
; /* save register value */
4829 vpushi(ll
>> 32); /* second word */
4830 } else if (r
>= VT_CONST
|| /* XXX: test to VT_CONST incorrect ? */
4831 (vtop
->r
& VT_LVAL
)) {
4832 /* We do not want to modifier the long long
4833 pointer here, so the safest (and less
4834 efficient) is to save all the other registers
4835 in the stack. XXX: totally inefficient. */
4837 /* load from memory */
4840 vtop
[-1].r
= r
; /* save register value */
4841 /* increment pointer to get second word */
4842 vtop
->type
.t
= VT_INT
;
4848 /* move registers */
4851 vtop
[-1].r
= r
; /* save register value */
4852 vtop
->r
= vtop
[-1].r2
;
4854 /* allocate second register */
4861 /* write second register */
4863 } else if ((vtop
->r
& VT_LVAL
) && !is_float(vtop
->type
.t
)) {
4865 /* lvalue of scalar type : need to use lvalue type
4866 because of possible cast */
4869 /* compute memory access type */
4870 if (vtop
->r
& VT_LVAL_BYTE
)
4872 else if (vtop
->r
& VT_LVAL_SHORT
)
4874 if (vtop
->r
& VT_LVAL_UNSIGNED
)
4878 /* restore wanted type */
4881 /* one register type load */
4886 #ifdef TCC_TARGET_C67
4887 /* uses register pairs for doubles */
4888 if ((vtop
->type
.t
& VT_BTYPE
) == VT_DOUBLE
)
4895 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
4896 void gv2(int rc1
, int rc2
)
4900 /* generate more generic register first. But VT_JMP or VT_CMP
4901 values must be generated first in all cases to avoid possible
4903 v
= vtop
[0].r
& VT_VALMASK
;
4904 if (v
!= VT_CMP
&& (v
& ~1) != VT_JMP
&& rc1
<= rc2
) {
4909 /* test if reload is needed for first register */
4910 if ((vtop
[-1].r
& VT_VALMASK
) >= VT_CONST
) {
4920 /* test if reload is needed for first register */
4921 if ((vtop
[0].r
& VT_VALMASK
) >= VT_CONST
) {
4927 /* expand long long on stack in two int registers */
4932 u
= vtop
->type
.t
& VT_UNSIGNED
;
4935 vtop
[0].r
= vtop
[-1].r2
;
4936 vtop
[0].r2
= VT_CONST
;
4937 vtop
[-1].r2
= VT_CONST
;
4938 vtop
[0].type
.t
= VT_INT
| u
;
4939 vtop
[-1].type
.t
= VT_INT
| u
;
4942 #ifdef TCC_TARGET_ARM
4943 /* expand long long on stack */
4944 void lexpand_nr(void)
4948 u
= vtop
->type
.t
& VT_UNSIGNED
;
4950 vtop
->r2
= VT_CONST
;
4951 vtop
->type
.t
= VT_INT
| u
;
4952 v
=vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
);
4953 if (v
== VT_CONST
) {
4954 vtop
[-1].c
.ui
= vtop
->c
.ull
;
4955 vtop
->c
.ui
= vtop
->c
.ull
>> 32;
4957 } else if (v
== (VT_LVAL
|VT_CONST
) || v
== (VT_LVAL
|VT_LOCAL
)) {
4959 vtop
->r
= vtop
[-1].r
;
4960 } else if (v
> VT_CONST
) {
4964 vtop
->r
= vtop
[-1].r2
;
4965 vtop
[-1].r2
= VT_CONST
;
4966 vtop
[-1].type
.t
= VT_INT
| u
;
4970 /* build a long long from two ints */
4973 gv2(RC_INT
, RC_INT
);
4974 vtop
[-1].r2
= vtop
[0].r
;
4975 vtop
[-1].type
.t
= t
;
4979 /* rotate n first stack elements to the bottom
4980 I1 ... In -> I2 ... In I1 [top is right]
4988 for(i
=-n
+1;i
!=0;i
++)
4989 vtop
[i
] = vtop
[i
+1];
4993 /* rotate n first stack elements to the top
4994 I1 ... In -> In I1 ... I(n-1) [top is right]
5002 for(i
= 0;i
< n
- 1; i
++)
5003 vtop
[-i
] = vtop
[-i
- 1];
5007 #ifdef TCC_TARGET_ARM
5008 /* like vrott but in other direction
5009 In ... I1 -> I(n-1) ... I1 In [top is right]
5017 for(i
= n
- 1; i
> 0; i
--)
5018 vtop
[-i
] = vtop
[-i
+ 1];
5023 /* pop stack value */
5027 v
= vtop
->r
& VT_VALMASK
;
5028 #ifdef TCC_TARGET_I386
5029 /* for x86, we need to pop the FP stack */
5030 if (v
== TREG_ST0
&& !nocode_wanted
) {
5031 o(0xd9dd); /* fstp %st(1) */
5034 if (v
== VT_JMP
|| v
== VT_JMPI
) {
5035 /* need to put correct jump if && or || without test */
5041 /* convert stack entry to register and duplicate its value in another
5049 if ((t
& VT_BTYPE
) == VT_LLONG
) {
5056 /* stack: H L L1 H1 */
5064 /* duplicate value */
5075 load(r1
, &sv
); /* move r to r1 */
5077 /* duplicates value */
5082 /* generate CPU independent (unsigned) long long operations */
5083 void gen_opl(int op
)
5085 int t
, a
, b
, op1
, c
, i
;
5092 func
= TOK___divdi3
;
5095 func
= TOK___udivdi3
;
5098 func
= TOK___moddi3
;
5101 func
= TOK___umoddi3
;
5103 /* call generic long long function */
5104 vpush_global_sym(&func_old_type
, func
);
5109 vtop
->r2
= REG_LRET
;
5122 /* stack: L1 H1 L2 H2 */
5127 vtop
[-2] = vtop
[-3];
5130 /* stack: H1 H2 L1 L2 */
5136 /* stack: H1 H2 L1 L2 ML MH */
5139 /* stack: ML MH H1 H2 L1 L2 */
5143 /* stack: ML MH H1 L2 H2 L1 */
5148 /* stack: ML MH M1 M2 */
5151 } else if (op
== '+' || op
== '-') {
5152 /* XXX: add non carry method too (for MIPS or alpha) */
5158 /* stack: H1 H2 (L1 op L2) */
5161 gen_op(op1
+ 1); /* TOK_xxxC2 */
5164 /* stack: H1 H2 (L1 op L2) */
5167 /* stack: (L1 op L2) H1 H2 */
5169 /* stack: (L1 op L2) (H1 op H2) */
5177 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
) {
5178 t
= vtop
[-1].type
.t
;
5182 /* stack: L H shift */
5184 /* constant: simpler */
5185 /* NOTE: all comments are for SHL. the other cases are
5186 done by swaping words */
5197 if (op
!= TOK_SAR
) {
5230 /* XXX: should provide a faster fallback on x86 ? */
5233 func
= TOK___sardi3
;
5236 func
= TOK___shrdi3
;
5239 func
= TOK___shldi3
;
5245 /* compare operations */
5251 /* stack: L1 H1 L2 H2 */
5253 vtop
[-1] = vtop
[-2];
5255 /* stack: L1 L2 H1 H2 */
5258 /* when values are equal, we need to compare low words. since
5259 the jump is inverted, we invert the test too. */
5262 else if (op1
== TOK_GT
)
5264 else if (op1
== TOK_ULT
)
5266 else if (op1
== TOK_UGT
)
5271 if (op1
!= TOK_NE
) {
5275 /* generate non equal test */
5276 /* XXX: NOT PORTABLE yet */
5280 #if defined(TCC_TARGET_I386)
5281 b
= psym(0x850f, 0);
5282 #elif defined(TCC_TARGET_ARM)
5284 o(0x1A000000 | encbranch(ind
, 0, 1));
5285 #elif defined(TCC_TARGET_C67)
5286 error("not implemented");
5288 #error not supported
5292 /* compare low. Always unsigned */
5296 else if (op1
== TOK_LE
)
5298 else if (op1
== TOK_GT
)
5300 else if (op1
== TOK_GE
)
5310 /* handle integer constant optimizations and various machine
5312 void gen_opic(int op
)
5319 /* currently, we cannot do computations with forward symbols */
5320 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5321 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5325 case '+': v1
->c
.i
+= fc
; break;
5326 case '-': v1
->c
.i
-= fc
; break;
5327 case '&': v1
->c
.i
&= fc
; break;
5328 case '^': v1
->c
.i
^= fc
; break;
5329 case '|': v1
->c
.i
|= fc
; break;
5330 case '*': v1
->c
.i
*= fc
; break;
5337 /* if division by zero, generate explicit division */
5340 error("division by zero in constant");
5344 default: v1
->c
.i
/= fc
; break;
5345 case '%': v1
->c
.i
%= fc
; break;
5346 case TOK_UDIV
: v1
->c
.i
= (unsigned)v1
->c
.i
/ fc
; break;
5347 case TOK_UMOD
: v1
->c
.i
= (unsigned)v1
->c
.i
% fc
; break;
5350 case TOK_SHL
: v1
->c
.i
<<= fc
; break;
5351 case TOK_SHR
: v1
->c
.i
= (unsigned)v1
->c
.i
>> fc
; break;
5352 case TOK_SAR
: v1
->c
.i
>>= fc
; break;
5354 case TOK_ULT
: v1
->c
.i
= (unsigned)v1
->c
.i
< (unsigned)fc
; break;
5355 case TOK_UGE
: v1
->c
.i
= (unsigned)v1
->c
.i
>= (unsigned)fc
; break;
5356 case TOK_EQ
: v1
->c
.i
= v1
->c
.i
== fc
; break;
5357 case TOK_NE
: v1
->c
.i
= v1
->c
.i
!= fc
; break;
5358 case TOK_ULE
: v1
->c
.i
= (unsigned)v1
->c
.i
<= (unsigned)fc
; break;
5359 case TOK_UGT
: v1
->c
.i
= (unsigned)v1
->c
.i
> (unsigned)fc
; break;
5360 case TOK_LT
: v1
->c
.i
= v1
->c
.i
< fc
; break;
5361 case TOK_GE
: v1
->c
.i
= v1
->c
.i
>= fc
; break;
5362 case TOK_LE
: v1
->c
.i
= v1
->c
.i
<= fc
; break;
5363 case TOK_GT
: v1
->c
.i
= v1
->c
.i
> fc
; break;
5365 case TOK_LAND
: v1
->c
.i
= v1
->c
.i
&& fc
; break;
5366 case TOK_LOR
: v1
->c
.i
= v1
->c
.i
|| fc
; break;
5372 /* if commutative ops, put c2 as constant */
5373 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
5374 op
== '|' || op
== '*')) {
5379 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
5382 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
5383 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
5389 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
5390 /* try to use shifts instead of muls or divs */
5391 if (fc
> 0 && (fc
& (fc
- 1)) == 0) {
5400 else if (op
== TOK_PDIV
)
5406 } else if (c2
&& (op
== '+' || op
== '-') &&
5407 (vtop
[-1].r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) ==
5408 (VT_CONST
| VT_SYM
)) {
5409 /* symbol + constant case */
5416 if (!nocode_wanted
) {
5417 /* call low level op generator */
5426 /* generate a floating point operation with constant propagation */
5427 void gen_opif(int op
)
5435 /* currently, we cannot do computations with forward symbols */
5436 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5437 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5439 if (v1
->type
.t
== VT_FLOAT
) {
5442 } else if (v1
->type
.t
== VT_DOUBLE
) {
5450 /* NOTE: we only do constant propagation if finite number (not
5451 NaN or infinity) (ANSI spec) */
5452 if (!ieee_finite(f1
) || !ieee_finite(f2
))
5456 case '+': f1
+= f2
; break;
5457 case '-': f1
-= f2
; break;
5458 case '*': f1
*= f2
; break;
5462 error("division by zero in constant");
5467 /* XXX: also handles tests ? */
5471 /* XXX: overflow test ? */
5472 if (v1
->type
.t
== VT_FLOAT
) {
5474 } else if (v1
->type
.t
== VT_DOUBLE
) {
5482 if (!nocode_wanted
) {
5490 static int pointed_size(CType
*type
)
5493 return type_size(pointed_type(type
), &align
);
5496 static inline int is_null_pointer(SValue
*p
)
5498 if ((p
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
5500 return ((p
->type
.t
& VT_BTYPE
) == VT_INT
&& p
->c
.i
== 0) ||
5501 ((p
->type
.t
& VT_BTYPE
) == VT_LLONG
&& p
->c
.ll
== 0);
5504 static inline int is_integer_btype(int bt
)
5506 return (bt
== VT_BYTE
|| bt
== VT_SHORT
||
5507 bt
== VT_INT
|| bt
== VT_LLONG
);
5510 /* check types for comparison or substraction of pointers */
5511 static void check_comparison_pointer_types(SValue
*p1
, SValue
*p2
, int op
)
5513 CType
*type1
, *type2
, tmp_type1
, tmp_type2
;
5516 /* null pointers are accepted for all comparisons as gcc */
5517 if (is_null_pointer(p1
) || is_null_pointer(p2
))
5521 bt1
= type1
->t
& VT_BTYPE
;
5522 bt2
= type2
->t
& VT_BTYPE
;
5523 /* accept comparison between pointer and integer with a warning */
5524 if ((is_integer_btype(bt1
) || is_integer_btype(bt2
)) && op
!= '-') {
5525 warning("comparison between pointer and integer");
5529 /* both must be pointers or implicit function pointers */
5530 if (bt1
== VT_PTR
) {
5531 type1
= pointed_type(type1
);
5532 } else if (bt1
!= VT_FUNC
)
5533 goto invalid_operands
;
5535 if (bt2
== VT_PTR
) {
5536 type2
= pointed_type(type2
);
5537 } else if (bt2
!= VT_FUNC
) {
5539 error("invalid operands to binary %s", get_tok_str(op
, NULL
));
5541 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
5542 (type2
->t
& VT_BTYPE
) == VT_VOID
)
5546 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5547 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
5548 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
5549 /* gcc-like error if '-' is used */
5551 goto invalid_operands
;
5553 warning("comparison of distinct pointer types lacks a cast");
5557 /* generic gen_op: handles types problems */
5560 int u
, t1
, t2
, bt1
, bt2
, t
;
5563 t1
= vtop
[-1].type
.t
;
5564 t2
= vtop
[0].type
.t
;
5565 bt1
= t1
& VT_BTYPE
;
5566 bt2
= t2
& VT_BTYPE
;
5568 if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
5569 /* at least one operand is a pointer */
5570 /* relationnal op: must be both pointers */
5571 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
5572 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5573 /* pointers are handled are unsigned */
5574 t
= VT_INT
| VT_UNSIGNED
;
5577 /* if both pointers, then it must be the '-' op */
5578 if (bt1
== VT_PTR
&& bt2
== VT_PTR
) {
5580 error("cannot use pointers here");
5581 check_comparison_pointer_types(vtop
- 1, vtop
, op
);
5582 /* XXX: check that types are compatible */
5583 u
= pointed_size(&vtop
[-1].type
);
5585 /* set to integer type */
5586 vtop
->type
.t
= VT_INT
;
5590 /* exactly one pointer : must be '+' or '-'. */
5591 if (op
!= '-' && op
!= '+')
5592 error("cannot use pointers here");
5593 /* Put pointer as first operand */
5594 if (bt2
== VT_PTR
) {
5598 type1
= vtop
[-1].type
;
5599 /* XXX: cast to int ? (long long case) */
5600 vpushi(pointed_size(&vtop
[-1].type
));
5602 #ifdef CONFIG_TCC_BCHECK
5603 /* if evaluating constant expression, no code should be
5604 generated, so no bound check */
5605 if (do_bounds_check
&& !const_wanted
) {
5606 /* if bounded pointers, we generate a special code to
5613 gen_bounded_ptr_add();
5619 /* put again type if gen_opic() swaped operands */
5622 } else if (is_float(bt1
) || is_float(bt2
)) {
5623 /* compute bigger type and do implicit casts */
5624 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
5626 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
5631 /* floats can only be used for a few operations */
5632 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
5633 (op
< TOK_ULT
|| op
> TOK_GT
))
5634 error("invalid operands for binary operation");
5636 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
5637 /* cast to biggest op */
5639 /* convert to unsigned if it does not fit in a long long */
5640 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
5641 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
5645 /* integer operations */
5647 /* convert to unsigned if it does not fit in an integer */
5648 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
5649 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
5652 /* XXX: currently, some unsigned operations are explicit, so
5653 we modify them here */
5654 if (t
& VT_UNSIGNED
) {
5661 else if (op
== TOK_LT
)
5663 else if (op
== TOK_GT
)
5665 else if (op
== TOK_LE
)
5667 else if (op
== TOK_GE
)
5674 /* special case for shifts and long long: we keep the shift as
5676 if (op
== TOK_SHR
|| op
== TOK_SAR
|| op
== TOK_SHL
)
5681 else if ((t
& VT_BTYPE
) == VT_LLONG
)
5685 if (op
>= TOK_ULT
&& op
<= TOK_GT
) {
5686 /* relationnal op: the result is an int */
5687 vtop
->type
.t
= VT_INT
;
5694 /* generic itof for unsigned long long case */
5695 void gen_cvt_itof1(int t
)
5697 if ((vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
)) ==
5698 (VT_LLONG
| VT_UNSIGNED
)) {
5701 vpush_global_sym(&func_old_type
, TOK___ulltof
);
5702 else if (t
== VT_DOUBLE
)
5703 vpush_global_sym(&func_old_type
, TOK___ulltod
);
5705 vpush_global_sym(&func_old_type
, TOK___ulltold
);
5715 /* generic ftoi for unsigned long long case */
5716 void gen_cvt_ftoi1(int t
)
5720 if (t
== (VT_LLONG
| VT_UNSIGNED
)) {
5721 /* not handled natively */
5722 st
= vtop
->type
.t
& VT_BTYPE
;
5724 vpush_global_sym(&func_old_type
, TOK___fixunssfdi
);
5725 else if (st
== VT_DOUBLE
)
5726 vpush_global_sym(&func_old_type
, TOK___fixunsdfdi
);
5728 vpush_global_sym(&func_old_type
, TOK___fixunsxfdi
);
5733 vtop
->r2
= REG_LRET
;
5739 /* force char or short cast */
5740 void force_charshort_cast(int t
)
5744 /* XXX: add optimization if lvalue : just change type and offset */
5749 if (t
& VT_UNSIGNED
) {
5750 vpushi((1 << bits
) - 1);
5761 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
5762 static void gen_cast(CType
*type
)
5764 int sbt
, dbt
, sf
, df
, c
;
5766 /* special delayed cast for char/short */
5767 /* XXX: in some cases (multiple cascaded casts), it may still
5769 if (vtop
->r
& VT_MUSTCAST
) {
5770 vtop
->r
&= ~VT_MUSTCAST
;
5771 force_charshort_cast(vtop
->type
.t
);
5774 /* bitfields first get cast to ints */
5775 if (vtop
->type
.t
& VT_BITFIELD
) {
5779 dbt
= type
->t
& (VT_BTYPE
| VT_UNSIGNED
);
5780 sbt
= vtop
->type
.t
& (VT_BTYPE
| VT_UNSIGNED
);
5782 if (sbt
!= dbt
&& !nocode_wanted
) {
5785 c
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
5787 /* convert from fp to fp */
5789 /* constant case: we can do it now */
5790 /* XXX: in ISOC, cannot do it if error in convert */
5791 if (dbt
== VT_FLOAT
&& sbt
== VT_DOUBLE
)
5792 vtop
->c
.f
= (float)vtop
->c
.d
;
5793 else if (dbt
== VT_FLOAT
&& sbt
== VT_LDOUBLE
)
5794 vtop
->c
.f
= (float)vtop
->c
.ld
;
5795 else if (dbt
== VT_DOUBLE
&& sbt
== VT_FLOAT
)
5796 vtop
->c
.d
= (double)vtop
->c
.f
;
5797 else if (dbt
== VT_DOUBLE
&& sbt
== VT_LDOUBLE
)
5798 vtop
->c
.d
= (double)vtop
->c
.ld
;
5799 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_FLOAT
)
5800 vtop
->c
.ld
= (long double)vtop
->c
.f
;
5801 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_DOUBLE
)
5802 vtop
->c
.ld
= (long double)vtop
->c
.d
;
5804 /* non constant case: generate code */
5808 /* convert int to fp */
5811 case VT_LLONG
| VT_UNSIGNED
:
5813 /* XXX: add const cases for long long */
5815 case VT_INT
| VT_UNSIGNED
:
5817 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.ui
; break;
5818 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.ui
; break;
5819 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.ui
; break;
5824 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.i
; break;
5825 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.i
; break;
5826 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.i
; break;
5832 #if !defined(TCC_TARGET_ARM)
5839 /* convert fp to int */
5840 /* we handle char/short/etc... with generic code */
5841 if (dbt
!= (VT_INT
| VT_UNSIGNED
) &&
5842 dbt
!= (VT_LLONG
| VT_UNSIGNED
) &&
5847 case VT_LLONG
| VT_UNSIGNED
:
5849 /* XXX: add const cases for long long */
5851 case VT_INT
| VT_UNSIGNED
:
5853 case VT_FLOAT
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5854 case VT_DOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5855 case VT_LDOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
5861 case VT_FLOAT
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5862 case VT_DOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5863 case VT_LDOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
5871 if (dbt
== VT_INT
&& (type
->t
& (VT_BTYPE
| VT_UNSIGNED
)) != dbt
) {
5872 /* additional cast for char/short/bool... */
5876 } else if ((dbt
& VT_BTYPE
) == VT_LLONG
) {
5877 if ((sbt
& VT_BTYPE
) != VT_LLONG
) {
5878 /* scalar to long long */
5880 if (sbt
== (VT_INT
| VT_UNSIGNED
))
5881 vtop
->c
.ll
= vtop
->c
.ui
;
5883 vtop
->c
.ll
= vtop
->c
.i
;
5885 /* machine independent conversion */
5887 /* generate high word */
5888 if (sbt
== (VT_INT
| VT_UNSIGNED
)) {
5896 /* patch second register */
5897 vtop
[-1].r2
= vtop
->r
;
5901 } else if (dbt
== VT_BOOL
) {
5902 /* scalar to bool */
5905 } else if ((dbt
& VT_BTYPE
) == VT_BYTE
||
5906 (dbt
& VT_BTYPE
) == VT_SHORT
) {
5907 force_charshort_cast(dbt
);
5908 } else if ((dbt
& VT_BTYPE
) == VT_INT
) {
5910 if (sbt
== VT_LLONG
) {
5911 /* from long long: just take low order word */
5915 /* if lvalue and single word type, nothing to do because
5916 the lvalue already contains the real type size (see
5917 VT_LVAL_xxx constants) */
5923 /* return type size. Put alignment at 'a' */
5924 static int type_size(CType
*type
, int *a
)
5929 bt
= type
->t
& VT_BTYPE
;
5930 if (bt
== VT_STRUCT
) {
5935 } else if (bt
== VT_PTR
) {
5936 if (type
->t
& VT_ARRAY
) {
5938 return type_size(&s
->type
, a
) * s
->c
;
5943 } else if (bt
== VT_LDOUBLE
) {
5945 return LDOUBLE_SIZE
;
5946 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
5947 #ifdef TCC_TARGET_I386
5953 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
5956 } else if (bt
== VT_SHORT
) {
5960 /* char, void, function, _Bool */
5966 /* return the pointed type of t */
5967 static inline CType
*pointed_type(CType
*type
)
5969 return &type
->ref
->type
;
5972 /* modify type so that its it is a pointer to type. */
5973 static void mk_pointer(CType
*type
)
5976 s
= sym_push(SYM_FIELD
, type
, 0, -1);
5977 type
->t
= VT_PTR
| (type
->t
& ~VT_TYPE
);
5981 /* compare function types. OLD functions match any new functions */
5982 static int is_compatible_func(CType
*type1
, CType
*type2
)
5988 if (!is_compatible_types(&s1
->type
, &s2
->type
))
5990 /* check func_call */
5993 /* XXX: not complete */
5994 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
5998 while (s1
!= NULL
) {
6001 if (!is_compatible_types(&s1
->type
, &s2
->type
))
6011 /* return true if type1 and type2 are exactly the same (including
6014 - enums are not checked as gcc __builtin_types_compatible_p ()
6016 static int is_compatible_types(CType
*type1
, CType
*type2
)
6020 t1
= type1
->t
& VT_TYPE
;
6021 t2
= type2
->t
& VT_TYPE
;
6022 /* XXX: bitfields ? */
6025 /* test more complicated cases */
6026 bt1
= t1
& VT_BTYPE
;
6027 if (bt1
== VT_PTR
) {
6028 type1
= pointed_type(type1
);
6029 type2
= pointed_type(type2
);
6030 return is_compatible_types(type1
, type2
);
6031 } else if (bt1
== VT_STRUCT
) {
6032 return (type1
->ref
== type2
->ref
);
6033 } else if (bt1
== VT_FUNC
) {
6034 return is_compatible_func(type1
, type2
);
6040 /* print a type. If 'varstr' is not NULL, then the variable is also
6041 printed in the type */
6043 /* XXX: add array and function pointers */
6044 void type_to_str(char *buf
, int buf_size
,
6045 CType
*type
, const char *varstr
)
6052 t
= type
->t
& VT_TYPE
;
6055 if (t
& VT_CONSTANT
)
6056 pstrcat(buf
, buf_size
, "const ");
6057 if (t
& VT_VOLATILE
)
6058 pstrcat(buf
, buf_size
, "volatile ");
6059 if (t
& VT_UNSIGNED
)
6060 pstrcat(buf
, buf_size
, "unsigned ");
6090 tstr
= "long double";
6092 pstrcat(buf
, buf_size
, tstr
);
6096 if (bt
== VT_STRUCT
)
6100 pstrcat(buf
, buf_size
, tstr
);
6101 v
= type
->ref
->v
& ~SYM_STRUCT
;
6102 if (v
>= SYM_FIRST_ANOM
)
6103 pstrcat(buf
, buf_size
, "<anonymous>");
6105 pstrcat(buf
, buf_size
, get_tok_str(v
, NULL
));
6109 type_to_str(buf
, buf_size
, &s
->type
, varstr
);
6110 pstrcat(buf
, buf_size
, "(");
6112 while (sa
!= NULL
) {
6113 type_to_str(buf1
, sizeof(buf1
), &sa
->type
, NULL
);
6114 pstrcat(buf
, buf_size
, buf1
);
6117 pstrcat(buf
, buf_size
, ", ");
6119 pstrcat(buf
, buf_size
, ")");
6123 pstrcpy(buf1
, sizeof(buf1
), "*");
6125 pstrcat(buf1
, sizeof(buf1
), varstr
);
6126 type_to_str(buf
, buf_size
, &s
->type
, buf1
);
6130 pstrcat(buf
, buf_size
, " ");
6131 pstrcat(buf
, buf_size
, varstr
);
6136 /* verify type compatibility to store vtop in 'dt' type, and generate
6138 static void gen_assign_cast(CType
*dt
)
6140 CType
*st
, *type1
, *type2
, tmp_type1
, tmp_type2
;
6141 char buf1
[256], buf2
[256];
6144 st
= &vtop
->type
; /* source type */
6145 dbt
= dt
->t
& VT_BTYPE
;
6146 sbt
= st
->t
& VT_BTYPE
;
6147 if (dt
->t
& VT_CONSTANT
)
6148 warning("assignment of read-only location");
6151 /* special cases for pointers */
6152 /* '0' can also be a pointer */
6153 if (is_null_pointer(vtop
))
6155 /* accept implicit pointer to integer cast with warning */
6156 if (is_integer_btype(sbt
)) {
6157 warning("assignment makes pointer from integer without a cast");
6160 type1
= pointed_type(dt
);
6161 /* a function is implicitely a function pointer */
6162 if (sbt
== VT_FUNC
) {
6163 if ((type1
->t
& VT_BTYPE
) != VT_VOID
&&
6164 !is_compatible_types(pointed_type(dt
), st
))
6171 type2
= pointed_type(st
);
6172 if ((type1
->t
& VT_BTYPE
) == VT_VOID
||
6173 (type2
->t
& VT_BTYPE
) == VT_VOID
) {
6174 /* void * can match anything */
6176 /* exact type match, except for unsigned */
6179 tmp_type1
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6180 tmp_type2
.t
&= ~(VT_UNSIGNED
| VT_CONSTANT
| VT_VOLATILE
);
6181 if (!is_compatible_types(&tmp_type1
, &tmp_type2
))
6184 /* check const and volatile */
6185 if ((!(type1
->t
& VT_CONSTANT
) && (type2
->t
& VT_CONSTANT
)) ||
6186 (!(type1
->t
& VT_VOLATILE
) && (type2
->t
& VT_VOLATILE
)))
6187 warning("assignment discards qualifiers from pointer target type");
6193 if (sbt
== VT_PTR
|| sbt
== VT_FUNC
) {
6194 warning("assignment makes integer from pointer without a cast");
6196 /* XXX: more tests */
6201 tmp_type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6202 tmp_type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6203 if (!is_compatible_types(&tmp_type1
, &tmp_type2
)) {
6205 type_to_str(buf1
, sizeof(buf1
), st
, NULL
);
6206 type_to_str(buf2
, sizeof(buf2
), dt
, NULL
);
6207 error("cannot cast '%s' to '%s'", buf1
, buf2
);
6215 /* store vtop in lvalue pushed on stack */
6218 int sbt
, dbt
, ft
, r
, t
, size
, align
, bit_size
, bit_pos
, rc
, delayed_cast
;
6220 ft
= vtop
[-1].type
.t
;
6221 sbt
= vtop
->type
.t
& VT_BTYPE
;
6222 dbt
= ft
& VT_BTYPE
;
6223 if (((sbt
== VT_INT
|| sbt
== VT_SHORT
) && dbt
== VT_BYTE
) ||
6224 (sbt
== VT_INT
&& dbt
== VT_SHORT
)) {
6225 /* optimize char/short casts */
6226 delayed_cast
= VT_MUSTCAST
;
6227 vtop
->type
.t
= ft
& VT_TYPE
;
6228 /* XXX: factorize */
6229 if (ft
& VT_CONSTANT
)
6230 warning("assignment of read-only location");
6233 if (!(ft
& VT_BITFIELD
))
6234 gen_assign_cast(&vtop
[-1].type
);
6237 if (sbt
== VT_STRUCT
) {
6238 /* if structure, only generate pointer */
6239 /* structure assignment : generate memcpy */
6240 /* XXX: optimize if small size */
6241 if (!nocode_wanted
) {
6242 size
= type_size(&vtop
->type
, &align
);
6244 vpush_global_sym(&func_old_type
, TOK_memcpy
);
6248 vtop
->type
.t
= VT_INT
;
6252 vtop
->type
.t
= VT_INT
;
6264 /* leave source on stack */
6265 } else if (ft
& VT_BITFIELD
) {
6266 /* bitfield store handling */
6267 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
6268 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
6269 /* remove bit field info to avoid loops */
6270 vtop
[-1].type
.t
= ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
6272 /* duplicate destination */
6274 vtop
[-1] = vtop
[-2];
6276 /* mask and shift source */
6277 vpushi((1 << bit_size
) - 1);
6281 /* load destination, mask and or with source */
6283 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
6289 #ifdef CONFIG_TCC_BCHECK
6290 /* bound check case */
6291 if (vtop
[-1].r
& VT_MUSTBOUND
) {
6297 if (!nocode_wanted
) {
6301 r
= gv(rc
); /* generate value */
6302 /* if lvalue was saved on stack, must read it */
6303 if ((vtop
[-1].r
& VT_VALMASK
) == VT_LLOCAL
) {
6305 t
= get_reg(RC_INT
);
6307 sv
.r
= VT_LOCAL
| VT_LVAL
;
6308 sv
.c
.ul
= vtop
[-1].c
.ul
;
6310 vtop
[-1].r
= t
| VT_LVAL
;
6313 /* two word case handling : store second register at word + 4 */
6314 if ((ft
& VT_BTYPE
) == VT_LLONG
) {
6316 /* convert to int to increment easily */
6317 vtop
->type
.t
= VT_INT
;
6323 /* XXX: it works because r2 is spilled last ! */
6324 store(vtop
->r2
, vtop
- 1);
6328 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
6329 vtop
->r
|= delayed_cast
;
6333 /* post defines POST/PRE add. c is the token ++ or -- */
6334 void inc(int post
, int c
)
6337 vdup(); /* save lvalue */
6339 gv_dup(); /* duplicate value */
6344 vpushi(c
- TOK_MID
);
6346 vstore(); /* store value */
6348 vpop(); /* if post op, return saved value */
6351 /* Parse GNUC __attribute__ extension. Currently, the following
6352 extensions are recognized:
6353 - aligned(n) : set data/function alignment.
6354 - packed : force data alignment to 1
6355 - section(x) : generate data/code in this section.
6356 - unused : currently ignored, but may be used someday.
6357 - regparm(n) : pass function parameters in registers (i386 only)
6359 static void parse_attribute(AttributeDef
*ad
)
6363 while (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
) {
6367 while (tok
!= ')') {
6368 if (tok
< TOK_IDENT
)
6369 expect("attribute name");
6377 expect("section name");
6378 ad
->section
= find_section(tcc_state
, (char *)tokc
.cstr
->data
);
6387 if (n
<= 0 || (n
& (n
- 1)) != 0)
6388 error("alignment must be a positive power of two");
6401 /* currently, no need to handle it because tcc does not
6402 track unused objects */
6406 /* currently, no need to handle it because tcc does not
6407 track unused objects */
6412 ad
->func_call
= FUNC_CDECL
;
6417 ad
->func_call
= FUNC_STDCALL
;
6419 #ifdef TCC_TARGET_I386
6429 ad
->func_call
= FUNC_FASTCALL1
+ n
- 1;
6435 ad
->func_call
= FUNC_FASTCALLW
;
6442 if (tcc_state
->warn_unsupported
)
6443 warning("'%s' attribute ignored", get_tok_str(t
, NULL
));
6444 /* skip parameters */
6445 /* XXX: skip parenthesis too */
6448 while (tok
!= ')' && tok
!= -1)
6463 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
6464 static void struct_decl(CType
*type
, int u
)
6466 int a
, v
, size
, align
, maxalign
, c
, offset
;
6467 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
;
6468 Sym
*s
, *ss
, *ass
, **ps
;
6472 a
= tok
; /* save decl type */
6477 /* struct already defined ? return it */
6479 expect("struct/union/enum name");
6483 error("invalid type");
6490 /* we put an undefined size for struct/union */
6491 s
= sym_push(v
| SYM_STRUCT
, &type1
, 0, -1);
6492 s
->r
= 0; /* default alignment is zero as gcc */
6493 /* put struct/union/enum name in type */
6501 error("struct/union/enum already defined");
6502 /* cannot be empty */
6504 /* non empty enums are not allowed */
6505 if (a
== TOK_ENUM
) {
6509 expect("identifier");
6515 /* enum symbols have static storage */
6516 ss
= sym_push(v
, &int_type
, VT_CONST
, c
);
6517 ss
->type
.t
|= VT_STATIC
;
6522 /* NOTE: we accept a trailing comma */
6532 while (tok
!= '}') {
6533 parse_btype(&btype
, &ad
);
6539 type_decl(&type1
, &ad
, &v
, TYPE_DIRECT
| TYPE_ABSTRACT
);
6540 if (v
== 0 && (type1
.t
& VT_BTYPE
) != VT_STRUCT
)
6541 expect("identifier");
6542 if ((type1
.t
& VT_BTYPE
) == VT_FUNC
||
6543 (type1
.t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
| VT_INLINE
)))
6544 error("invalid type for '%s'",
6545 get_tok_str(v
, NULL
));
6549 bit_size
= expr_const();
6550 /* XXX: handle v = 0 case for messages */
6552 error("negative width in bit-field '%s'",
6553 get_tok_str(v
, NULL
));
6554 if (v
&& bit_size
== 0)
6555 error("zero width for bit-field '%s'",
6556 get_tok_str(v
, NULL
));
6558 size
= type_size(&type1
, &align
);
6560 if (align
< ad
.aligned
)
6562 } else if (ad
.packed
) {
6564 } else if (*tcc_state
->pack_stack_ptr
) {
6565 if (align
> *tcc_state
->pack_stack_ptr
)
6566 align
= *tcc_state
->pack_stack_ptr
;
6569 if (bit_size
>= 0) {
6570 bt
= type1
.t
& VT_BTYPE
;
6576 error("bitfields must have scalar type");
6578 if (bit_size
> bsize
) {
6579 error("width of '%s' exceeds its type",
6580 get_tok_str(v
, NULL
));
6581 } else if (bit_size
== bsize
) {
6582 /* no need for bit fields */
6584 } else if (bit_size
== 0) {
6585 /* XXX: what to do if only padding in a
6587 /* zero size: means to pad */
6591 /* we do not have enough room ? */
6592 if ((bit_pos
+ bit_size
) > bsize
)
6595 /* XXX: handle LSB first */
6596 type1
.t
|= VT_BITFIELD
|
6597 (bit_pos
<< VT_STRUCT_SHIFT
) |
6598 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
6599 bit_pos
+= bit_size
;
6604 if (v
!= 0 || (type1
.t
& VT_BTYPE
) == VT_STRUCT
) {
6605 /* add new memory data only if starting
6607 if (lbit_pos
== 0) {
6608 if (a
== TOK_STRUCT
) {
6609 c
= (c
+ align
- 1) & -align
;
6617 if (align
> maxalign
)
6621 printf("add field %s offset=%d",
6622 get_tok_str(v
, NULL
), offset
);
6623 if (type1
.t
& VT_BITFIELD
) {
6624 printf(" pos=%d size=%d",
6625 (type1
.t
>> VT_STRUCT_SHIFT
) & 0x3f,
6626 (type1
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
6631 if (v
== 0 && (type1
.t
& VT_BTYPE
) == VT_STRUCT
) {
6633 while ((ass
= ass
->next
) != NULL
) {
6634 ss
= sym_push(ass
->v
, &ass
->type
, 0, offset
+ ass
->c
);
6639 ss
= sym_push(v
| SYM_FIELD
, &type1
, 0, offset
);
6643 if (tok
== ';' || tok
== TOK_EOF
)
6650 /* store size and alignment */
6651 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
6657 /* return 0 if no type declaration. otherwise, return the basic type
6660 static int parse_btype(CType
*type
, AttributeDef
*ad
)
6662 int t
, u
, type_found
, typespec_found
;
6666 memset(ad
, 0, sizeof(AttributeDef
));
6673 /* currently, we really ignore extension */
6683 if ((t
& VT_BTYPE
) != 0)
6684 error("too many basic types");
6700 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
6701 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6702 } else if ((t
& VT_BTYPE
) == VT_LONG
) {
6703 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
6717 if ((t
& VT_BTYPE
) == VT_LONG
) {
6718 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
6725 struct_decl(&type1
, VT_ENUM
);
6728 type
->ref
= type1
.ref
;
6732 struct_decl(&type1
, VT_STRUCT
);
6735 /* type modifiers */
6788 /* GNUC attribute */
6789 case TOK_ATTRIBUTE1
:
6790 case TOK_ATTRIBUTE2
:
6791 parse_attribute(ad
);
6798 parse_expr_type(&type1
);
6804 if (!s
|| !(s
->type
.t
& VT_TYPEDEF
))
6806 t
|= (s
->type
.t
& ~VT_TYPEDEF
);
6807 type
->ref
= s
->type
.ref
;
6814 if ((t
& (VT_SIGNED
|VT_UNSIGNED
)) == (VT_SIGNED
|VT_UNSIGNED
))
6815 error("signed and unsigned modifier");
6816 if (tcc_state
->char_is_unsigned
) {
6817 if ((t
& (VT_SIGNED
|VT_UNSIGNED
|VT_BTYPE
)) == VT_BYTE
)
6822 /* long is never used as type */
6823 if ((t
& VT_BTYPE
) == VT_LONG
)
6824 t
= (t
& ~VT_BTYPE
) | VT_INT
;
6829 /* convert a function parameter type (array to pointer and function to
6830 function pointer) */
6831 static inline void convert_parameter_type(CType
*pt
)
6833 /* remove const and volatile qualifiers (XXX: const could be used
6834 to indicate a const function parameter */
6835 pt
->t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
6836 /* array must be transformed to pointer according to ANSI C */
6838 if ((pt
->t
& VT_BTYPE
) == VT_FUNC
) {
6843 static void post_type(CType
*type
, AttributeDef
*ad
)
6846 Sym
**plast
, *s
, *first
;
6851 /* function declaration */
6858 /* read param name and compute offset */
6859 if (l
!= FUNC_OLD
) {
6860 if (!parse_btype(&pt
, &ad1
)) {
6862 error("invalid type");
6869 if ((pt
.t
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
6871 type_decl(&pt
, &ad1
, &n
, TYPE_DIRECT
| TYPE_ABSTRACT
);
6872 if ((pt
.t
& VT_BTYPE
) == VT_VOID
)
6873 error("parameter declared as void");
6878 expect("identifier");
6882 convert_parameter_type(&pt
);
6883 s
= sym_push(n
| SYM_FIELD
, &pt
, 0, 0);
6889 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
6896 /* if no parameters, then old type prototype */
6900 t1
= type
->t
& VT_STORAGE
;
6901 /* NOTE: const is ignored in returned type as it has a special
6902 meaning in gcc / C++ */
6903 type
->t
&= ~(VT_STORAGE
| VT_CONSTANT
);
6904 post_type(type
, ad
);
6905 /* we push a anonymous symbol which will contain the function prototype */
6906 s
= sym_push(SYM_FIELD
, type
, ad
->func_call
, l
);
6908 type
->t
= t1
| VT_FUNC
;
6910 } else if (tok
== '[') {
6911 /* array definition */
6917 error("invalid array size");
6920 /* parse next post type */
6921 t1
= type
->t
& VT_STORAGE
;
6922 type
->t
&= ~VT_STORAGE
;
6923 post_type(type
, ad
);
6925 /* we push a anonymous symbol which will contain the array
6927 s
= sym_push(SYM_FIELD
, type
, 0, n
);
6928 type
->t
= t1
| VT_ARRAY
| VT_PTR
;
6933 /* Parse a type declaration (except basic type), and return the type
6934 in 'type'. 'td' is a bitmask indicating which kind of type decl is
6935 expected. 'type' should contain the basic type. 'ad' is the
6936 attribute definition of the basic type. It can be modified by
6939 static void type_decl(CType
*type
, AttributeDef
*ad
, int *v
, int td
)
6942 CType type1
, *type2
;
6945 while (tok
== '*') {
6953 qualifiers
|= VT_CONSTANT
;
6958 qualifiers
|= VT_VOLATILE
;
6966 type
->t
|= qualifiers
;
6969 /* XXX: clarify attribute handling */
6970 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
6971 parse_attribute(ad
);
6973 /* recursive type */
6974 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
6975 type1
.t
= 0; /* XXX: same as int */
6978 /* XXX: this is not correct to modify 'ad' at this point, but
6979 the syntax is not clear */
6980 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
6981 parse_attribute(ad
);
6982 type_decl(&type1
, ad
, v
, td
);
6985 /* type identifier */
6986 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
6990 if (!(td
& TYPE_ABSTRACT
))
6991 expect("identifier");
6995 post_type(type
, ad
);
6996 if (tok
== TOK_ATTRIBUTE1
|| tok
== TOK_ATTRIBUTE2
)
6997 parse_attribute(ad
);
7000 /* append type at the end of type1 */
7013 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
7014 static int lvalue_type(int t
)
7019 if (bt
== VT_BYTE
|| bt
== VT_BOOL
)
7021 else if (bt
== VT_SHORT
)
7025 if (t
& VT_UNSIGNED
)
7026 r
|= VT_LVAL_UNSIGNED
;
7030 /* indirection with full error checking and bound check */
7031 static void indir(void)
7033 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
7035 if ((vtop
->r
& VT_LVAL
) && !nocode_wanted
)
7037 vtop
->type
= *pointed_type(&vtop
->type
);
7038 /* an array is never an lvalue */
7039 if (!(vtop
->type
.t
& VT_ARRAY
)) {
7040 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7041 /* if bound checking, the referenced pointer must be checked */
7042 if (do_bounds_check
)
7043 vtop
->r
|= VT_MUSTBOUND
;
7047 /* pass a parameter to a function and do type checking and casting */
7048 static void gfunc_param_typed(Sym
*func
, Sym
*arg
)
7053 func_type
= func
->c
;
7054 if (func_type
== FUNC_OLD
||
7055 (func_type
== FUNC_ELLIPSIS
&& arg
== NULL
)) {
7056 /* default casting : only need to convert float to double */
7057 if ((vtop
->type
.t
& VT_BTYPE
) == VT_FLOAT
) {
7061 } else if (arg
== NULL
) {
7062 error("too many arguments to function");
7065 type
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
7066 gen_assign_cast(&type
);
7070 /* parse an expression of the form '(type)' or '(expr)' and return its
7072 static void parse_expr_type(CType
*type
)
7078 if (parse_btype(type
, &ad
)) {
7079 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7086 static void parse_type(CType
*type
)
7091 if (!parse_btype(type
, &ad
)) {
7094 type_decl(type
, &ad
, &n
, TYPE_ABSTRACT
);
7097 static void vpush_tokc(int t
)
7101 vsetc(&type
, VT_CONST
, &tokc
);
7104 static void unary(void)
7106 int n
, t
, align
, size
, r
;
7111 /* XXX: GCC 2.95.3 does not generate a table although it should be
7125 vpush_tokc(VT_INT
| VT_UNSIGNED
);
7129 vpush_tokc(VT_LLONG
);
7133 vpush_tokc(VT_LLONG
| VT_UNSIGNED
);
7137 vpush_tokc(VT_FLOAT
);
7141 vpush_tokc(VT_DOUBLE
);
7145 vpush_tokc(VT_LDOUBLE
);
7148 case TOK___FUNCTION__
:
7150 goto tok_identifier
;
7156 /* special function name identifier */
7157 len
= strlen(funcname
) + 1;
7158 /* generate char[len] type */
7163 vpush_ref(&type
, data_section
, data_section
->data_offset
, len
);
7164 ptr
= section_ptr_add(data_section
, len
);
7165 memcpy(ptr
, funcname
, len
);
7170 #ifdef TCC_TARGET_PE
7171 t
= VT_SHORT
| VT_UNSIGNED
;
7177 /* string parsing */
7180 if (tcc_state
->warn_write_strings
)
7185 memset(&ad
, 0, sizeof(AttributeDef
));
7186 decl_initializer_alloc(&type
, &ad
, VT_CONST
, 2, 0, 0);
7191 if (parse_btype(&type
, &ad
)) {
7192 type_decl(&type
, &ad
, &n
, TYPE_ABSTRACT
);
7194 /* check ISOC99 compound literal */
7196 /* data is allocated locally by default */
7201 /* all except arrays are lvalues */
7202 if (!(type
.t
& VT_ARRAY
))
7203 r
|= lvalue_type(type
.t
);
7204 memset(&ad
, 0, sizeof(AttributeDef
));
7205 decl_initializer_alloc(&type
, &ad
, r
, 1, 0, 0);
7210 } else if (tok
== '{') {
7211 /* save all registers */
7213 /* statement expression : we do not accept break/continue
7214 inside as GCC does */
7215 block(NULL
, NULL
, NULL
, NULL
, 0, 1);
7230 /* functions names must be treated as function pointers,
7231 except for unary '&' and sizeof. Since we consider that
7232 functions are not lvalues, we only have to handle it
7233 there and in function calls. */
7234 /* arrays can also be used although they are not lvalues */
7235 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
&&
7236 !(vtop
->type
.t
& VT_ARRAY
))
7238 mk_pointer(&vtop
->type
);
7244 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
)
7245 vtop
->c
.i
= !vtop
->c
.i
;
7246 else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
7247 vtop
->c
.i
= vtop
->c
.i
^ 1;
7249 vseti(VT_JMP
, gtst(1, 0));
7259 /* in order to force cast, we add zero */
7261 if ((vtop
->type
.t
& VT_BTYPE
) == VT_PTR
)
7262 error("pointer not accepted for unary plus");
7272 parse_expr_type(&type
);
7276 size
= type_size(&type
, &align
);
7277 if (t
== TOK_SIZEOF
) {
7279 error("sizeof applied to an incomplete type");
7286 case TOK_builtin_types_compatible_p
:
7295 type1
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7296 type2
.t
&= ~(VT_CONSTANT
| VT_VOLATILE
);
7297 vpushi(is_compatible_types(&type1
, &type2
));
7300 case TOK_builtin_constant_p
:
7302 int saved_nocode_wanted
, res
;
7305 saved_nocode_wanted
= nocode_wanted
;
7308 res
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) == VT_CONST
;
7310 nocode_wanted
= saved_nocode_wanted
;
7330 goto tok_identifier
;
7332 /* allow to take the address of a label */
7333 if (tok
< TOK_UIDENT
)
7334 expect("label identifier");
7335 s
= label_find(tok
);
7337 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
7339 if (s
->r
== LABEL_DECLARED
)
7340 s
->r
= LABEL_FORWARD
;
7343 s
->type
.t
= VT_VOID
;
7344 mk_pointer(&s
->type
);
7345 s
->type
.t
|= VT_STATIC
;
7347 vset(&s
->type
, VT_CONST
| VT_SYM
, 0);
7356 expect("identifier");
7360 error("'%s' undeclared", get_tok_str(t
, NULL
));
7361 /* for simple function calls, we tolerate undeclared
7362 external reference to int() function */
7363 if (tcc_state
->warn_implicit_function_declaration
)
7364 warning("implicit declaration of function '%s'",
7365 get_tok_str(t
, NULL
));
7366 s
= external_global_sym(t
, &func_old_type
, 0);
7368 if ((s
->type
.t
& (VT_STATIC
| VT_INLINE
| VT_BTYPE
)) ==
7369 (VT_STATIC
| VT_INLINE
| VT_FUNC
)) {
7370 /* if referencing an inline function, then we generate a
7371 symbol to it if not already done. It will have the
7372 effect to generate code for it at the end of the
7373 compilation unit. Inline function as always
7374 generated in the text section. */
7376 put_extern_sym(s
, text_section
, 0, 0);
7377 r
= VT_SYM
| VT_CONST
;
7381 vset(&s
->type
, r
, s
->c
);
7382 /* if forward reference, we must point to s */
7383 if (vtop
->r
& VT_SYM
) {
7390 /* post operations */
7392 if (tok
== TOK_INC
|| tok
== TOK_DEC
) {
7395 } else if (tok
== '.' || tok
== TOK_ARROW
) {
7397 if (tok
== TOK_ARROW
)
7402 /* expect pointer on structure */
7403 if ((vtop
->type
.t
& VT_BTYPE
) != VT_STRUCT
)
7404 expect("struct or union");
7408 while ((s
= s
->next
) != NULL
) {
7413 error("field not found");
7414 /* add field offset to pointer */
7415 vtop
->type
= char_pointer_type
; /* change type to 'char *' */
7418 /* change type to field type, and set to lvalue */
7419 vtop
->type
= s
->type
;
7420 /* an array is never an lvalue */
7421 if (!(vtop
->type
.t
& VT_ARRAY
)) {
7422 vtop
->r
|= lvalue_type(vtop
->type
.t
);
7423 /* if bound checking, the referenced pointer must be checked */
7424 if (do_bounds_check
)
7425 vtop
->r
|= VT_MUSTBOUND
;
7428 } else if (tok
== '[') {
7434 } else if (tok
== '(') {
7440 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
) {
7441 /* pointer test (no array accepted) */
7442 if ((vtop
->type
.t
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
7443 vtop
->type
= *pointed_type(&vtop
->type
);
7444 if ((vtop
->type
.t
& VT_BTYPE
) != VT_FUNC
)
7448 expect("function pointer");
7451 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
7453 /* get return type */
7456 sa
= s
->next
; /* first parameter */
7458 /* compute first implicit argument if a structure is returned */
7459 if ((s
->type
.t
& VT_BTYPE
) == VT_STRUCT
) {
7460 /* get some space for the returned structure */
7461 size
= type_size(&s
->type
, &align
);
7462 loc
= (loc
- size
) & -align
;
7464 ret
.r
= VT_LOCAL
| VT_LVAL
;
7465 /* pass it as 'int' to avoid structure arg passing
7467 vseti(VT_LOCAL
, loc
);
7473 /* return in register */
7474 if (is_float(ret
.type
.t
)) {
7477 if ((ret
.type
.t
& VT_BTYPE
) == VT_LLONG
)
7486 gfunc_param_typed(s
, sa
);
7496 error("too few arguments to function");
7498 if (!nocode_wanted
) {
7499 gfunc_call(nb_args
);
7501 vtop
-= (nb_args
+ 1);
7504 vsetc(&ret
.type
, ret
.r
, &ret
.c
);
7512 static void uneq(void)
7518 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
7519 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
7520 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
7535 static void expr_prod(void)
7540 while (tok
== '*' || tok
== '/' || tok
== '%') {
7548 static void expr_sum(void)
7553 while (tok
== '+' || tok
== '-') {
7561 static void expr_shift(void)
7566 while (tok
== TOK_SHL
|| tok
== TOK_SAR
) {
7574 static void expr_cmp(void)
7579 while ((tok
>= TOK_ULE
&& tok
<= TOK_GT
) ||
7580 tok
== TOK_ULT
|| tok
== TOK_UGE
) {
7588 static void expr_cmpeq(void)
7593 while (tok
== TOK_EQ
|| tok
== TOK_NE
) {
7601 static void expr_and(void)
7604 while (tok
== '&') {
7611 static void expr_xor(void)
7614 while (tok
== '^') {
7621 static void expr_or(void)
7624 while (tok
== '|') {
7631 /* XXX: fix this mess */
7632 static void expr_land_const(void)
7635 while (tok
== TOK_LAND
) {
7642 /* XXX: fix this mess */
7643 static void expr_lor_const(void)
7646 while (tok
== TOK_LOR
) {
7653 /* only used if non constant */
7654 static void expr_land(void)
7659 if (tok
== TOK_LAND
) {
7663 if (tok
!= TOK_LAND
) {
7673 static void expr_lor(void)
7678 if (tok
== TOK_LOR
) {
7682 if (tok
!= TOK_LOR
) {
7692 /* XXX: better constant handling */
7693 static void expr_eq(void)
7695 int tt
, u
, r1
, r2
, rc
, t1
, t2
, bt1
, bt2
;
7697 CType type
, type1
, type2
;
7706 if (tok
== ':' && gnu_ext
) {
7722 if (vtop
!= vstack
) {
7723 /* needed to avoid having different registers saved in
7725 if (is_float(vtop
->type
.t
))
7732 if (tok
== ':' && gnu_ext
) {
7740 sv
= *vtop
; /* save value to handle it later */
7741 vtop
--; /* no vpop so that FP stack is not flushed */
7749 bt1
= t1
& VT_BTYPE
;
7751 bt2
= t2
& VT_BTYPE
;
7752 /* cast operands to correct type according to ISOC rules */
7753 if (is_float(bt1
) || is_float(bt2
)) {
7754 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
7755 type
.t
= VT_LDOUBLE
;
7756 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
7761 } else if (bt1
== VT_LLONG
|| bt2
== VT_LLONG
) {
7762 /* cast to biggest op */
7764 /* convert to unsigned if it does not fit in a long long */
7765 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
) ||
7766 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_LLONG
| VT_UNSIGNED
))
7767 type
.t
|= VT_UNSIGNED
;
7768 } else if (bt1
== VT_PTR
|| bt2
== VT_PTR
) {
7769 /* XXX: test pointer compatibility */
7771 } else if (bt1
== VT_STRUCT
|| bt2
== VT_STRUCT
) {
7772 /* XXX: test structure compatibility */
7774 } else if (bt1
== VT_VOID
|| bt2
== VT_VOID
) {
7775 /* NOTE: as an extension, we accept void on only one side */
7778 /* integer operations */
7780 /* convert to unsigned if it does not fit in an integer */
7781 if ((t1
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
) ||
7782 (t2
& (VT_BTYPE
| VT_UNSIGNED
)) == (VT_INT
| VT_UNSIGNED
))
7783 type
.t
|= VT_UNSIGNED
;
7786 /* now we convert second operand */
7789 if (is_float(type
.t
)) {
7791 } else if ((type
.t
& VT_BTYPE
) == VT_LLONG
) {
7792 /* for long longs, we use fixed registers to avoid having
7793 to handle a complicated move */
7798 /* this is horrible, but we must also convert first
7802 /* put again first value and cast it */
7813 static void gexpr(void)
7824 /* parse an expression and return its type without any side effect. */
7825 static void expr_type(CType
*type
)
7827 int saved_nocode_wanted
;
7829 saved_nocode_wanted
= nocode_wanted
;
7834 nocode_wanted
= saved_nocode_wanted
;
7837 /* parse a unary expression and return its type without any side
7839 static void unary_type(CType
*type
)
7851 /* parse a constant expression and return value in vtop. */
7852 static void expr_const1(void)
7861 /* parse an integer constant and return its value. */
7862 static int expr_const(void)
7866 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_SYM
)) != VT_CONST
)
7867 expect("constant expression");
7873 /* return the label token if current token is a label, otherwise
7875 static int is_label(void)
7879 /* fast test first */
7880 if (tok
< TOK_UIDENT
)
7882 /* no need to save tokc because tok is an identifier */
7889 unget_tok(last_tok
);
7894 static void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
,
7895 int case_reg
, int is_expr
)
7900 /* generate line number info */
7902 (last_line_num
!= file
->line_num
|| last_ind
!= ind
)) {
7903 put_stabn(N_SLINE
, 0, file
->line_num
, ind
- func_ind
);
7905 last_line_num
= file
->line_num
;
7909 /* default return value is (void) */
7911 vtop
->type
.t
= VT_VOID
;
7914 if (tok
== TOK_IF
) {
7921 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
7923 if (c
== TOK_ELSE
) {
7927 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, 0);
7928 gsym(d
); /* patch else jmp */
7931 } else if (tok
== TOK_WHILE
) {
7939 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
7943 } else if (tok
== '{') {
7947 /* record local declaration stack position */
7949 llabel
= local_label_stack
;
7950 /* handle local labels declarations */
7951 if (tok
== TOK_LABEL
) {
7954 if (tok
< TOK_UIDENT
)
7955 expect("label identifier");
7956 label_push(&local_label_stack
, tok
, LABEL_DECLARED
);
7966 while (tok
!= '}') {
7971 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
7974 /* pop locally defined labels */
7975 label_pop(&local_label_stack
, llabel
);
7976 /* pop locally defined symbols */
7977 sym_pop(&local_stack
, s
);
7979 } else if (tok
== TOK_RETURN
) {
7983 gen_assign_cast(&func_vt
);
7984 if ((func_vt
.t
& VT_BTYPE
) == VT_STRUCT
) {
7986 /* if returning structure, must copy it to implicit
7987 first pointer arg location */
7990 vset(&type
, VT_LOCAL
| VT_LVAL
, func_vc
);
7993 /* copy structure value to pointer */
7995 } else if (is_float(func_vt
.t
)) {
8000 vtop
--; /* NOT vpop() because on x86 it would flush the fp stack */
8003 rsym
= gjmp(rsym
); /* jmp */
8004 } else if (tok
== TOK_BREAK
) {
8007 error("cannot break");
8008 *bsym
= gjmp(*bsym
);
8011 } else if (tok
== TOK_CONTINUE
) {
8014 error("cannot continue");
8015 *csym
= gjmp(*csym
);
8018 } else if (tok
== TOK_FOR
) {
8045 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8050 if (tok
== TOK_DO
) {
8055 block(&a
, &b
, case_sym
, def_sym
, case_reg
, 0);
8066 if (tok
== TOK_SWITCH
) {
8070 /* XXX: other types than integer */
8071 case_reg
= gv(RC_INT
);
8075 b
= gjmp(0); /* jump to first case */
8077 block(&a
, csym
, &b
, &c
, case_reg
, 0);
8078 /* if no default, jmp after switch */
8086 if (tok
== TOK_CASE
) {
8093 if (gnu_ext
&& tok
== TOK_DOTS
) {
8097 warning("empty case range");
8099 /* since a case is like a label, we must skip it with a jmp */
8106 *case_sym
= gtst(1, 0);
8109 *case_sym
= gtst(1, 0);
8113 *case_sym
= gtst(1, *case_sym
);
8118 goto block_after_label
;
8120 if (tok
== TOK_DEFAULT
) {
8126 error("too many 'default'");
8129 goto block_after_label
;
8131 if (tok
== TOK_GOTO
) {
8133 if (tok
== '*' && gnu_ext
) {
8137 if ((vtop
->type
.t
& VT_BTYPE
) != VT_PTR
)
8140 } else if (tok
>= TOK_UIDENT
) {
8141 s
= label_find(tok
);
8142 /* put forward definition if needed */
8144 s
= label_push(&global_label_stack
, tok
, LABEL_FORWARD
);
8146 if (s
->r
== LABEL_DECLARED
)
8147 s
->r
= LABEL_FORWARD
;
8149 /* label already defined */
8150 if (s
->r
& LABEL_FORWARD
)
8151 s
->next
= (void *)gjmp((long)s
->next
);
8153 gjmp_addr((long)s
->next
);
8156 expect("label identifier");
8159 } else if (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
) {
8167 if (s
->r
== LABEL_DEFINED
)
8168 error("duplicate label '%s'", get_tok_str(s
->v
, NULL
));
8169 gsym((long)s
->next
);
8170 s
->r
= LABEL_DEFINED
;
8172 s
= label_push(&global_label_stack
, b
, LABEL_DEFINED
);
8174 s
->next
= (void *)ind
;
8175 /* we accept this, but it is a mistake */
8178 warning("deprecated use of label at end of compound statement");
8182 block(bsym
, csym
, case_sym
, def_sym
, case_reg
, is_expr
);
8185 /* expression case */
8200 /* t is the array or struct type. c is the array or struct
8201 address. cur_index/cur_field is the pointer to the current
8202 value. 'size_only' is true if only size info is needed (only used
8204 static void decl_designator(CType
*type
, Section
*sec
, unsigned long c
,
8205 int *cur_index
, Sym
**cur_field
,
8209 int notfirst
, index
, index_last
, align
, l
, nb_elems
, elem_size
;
8215 if (gnu_ext
&& (l
= is_label()) != 0)
8217 while (tok
== '[' || tok
== '.') {
8219 if (!(type
->t
& VT_ARRAY
))
8220 expect("array type");
8223 index
= expr_const();
8224 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
8225 expect("invalid index");
8226 if (tok
== TOK_DOTS
&& gnu_ext
) {
8228 index_last
= expr_const();
8229 if (index_last
< 0 ||
8230 (s
->c
>= 0 && index_last
>= s
->c
) ||
8232 expect("invalid index");
8238 *cur_index
= index_last
;
8239 type
= pointed_type(type
);
8240 elem_size
= type_size(type
, &align
);
8241 c
+= index
* elem_size
;
8242 /* NOTE: we only support ranges for last designator */
8243 nb_elems
= index_last
- index
+ 1;
8244 if (nb_elems
!= 1) {
8253 if ((type
->t
& VT_BTYPE
) != VT_STRUCT
)
8254 expect("struct/union type");
8267 /* XXX: fix this mess by using explicit storage field */
8269 type1
.t
|= (type
->t
& ~VT_TYPE
);
8283 if (type
->t
& VT_ARRAY
) {
8285 type
= pointed_type(type
);
8286 c
+= index
* type_size(type
, &align
);
8290 error("too many field init");
8291 /* XXX: fix this mess by using explicit storage field */
8293 type1
.t
|= (type
->t
& ~VT_TYPE
);
8298 decl_initializer(type
, sec
, c
, 0, size_only
);
8300 /* XXX: make it more general */
8301 if (!size_only
&& nb_elems
> 1) {
8302 unsigned long c_end
;
8307 error("range init not supported yet for dynamic storage");
8308 c_end
= c
+ nb_elems
* elem_size
;
8309 if (c_end
> sec
->data_allocated
)
8310 section_realloc(sec
, c_end
);
8311 src
= sec
->data
+ c
;
8313 for(i
= 1; i
< nb_elems
; i
++) {
8315 memcpy(dst
, src
, elem_size
);
8321 #define EXPR_CONST 1
8324 /* store a value or an expression directly in global data or in local array */
8325 static void init_putv(CType
*type
, Section
*sec
, unsigned long c
,
8326 int v
, int expr_type
)
8328 int saved_global_expr
, bt
, bit_pos
, bit_size
;
8330 unsigned long long bit_mask
;
8338 /* compound literals must be allocated globally in this case */
8339 saved_global_expr
= global_expr
;
8342 global_expr
= saved_global_expr
;
8343 /* NOTE: symbols are accepted */
8344 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) != VT_CONST
)
8345 error("initializer element is not constant");
8353 dtype
.t
&= ~VT_CONSTANT
; /* need to do that to avoid false warning */
8356 /* XXX: not portable */
8357 /* XXX: generate error if incorrect relocation */
8358 gen_assign_cast(&dtype
);
8359 bt
= type
->t
& VT_BTYPE
;
8360 ptr
= sec
->data
+ c
;
8361 /* XXX: make code faster ? */
8362 if (!(type
->t
& VT_BITFIELD
)) {
8367 bit_pos
= (vtop
->type
.t
>> VT_STRUCT_SHIFT
) & 0x3f;
8368 bit_size
= (vtop
->type
.t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
8369 bit_mask
= (1LL << bit_size
) - 1;
8371 if ((vtop
->r
& VT_SYM
) &&
8377 (bt
== VT_INT
&& bit_size
!= 32)))
8378 error("initializer element is not computable at load time");
8381 *(char *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8384 *(short *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8387 *(double *)ptr
= vtop
->c
.d
;
8390 *(long double *)ptr
= vtop
->c
.ld
;
8393 *(long long *)ptr
|= (vtop
->c
.ll
& bit_mask
) << bit_pos
;
8396 if (vtop
->r
& VT_SYM
) {
8397 greloc(sec
, vtop
->sym
, c
, R_DATA_32
);
8399 *(int *)ptr
|= (vtop
->c
.i
& bit_mask
) << bit_pos
;
8404 vset(&dtype
, VT_LOCAL
, c
);
8411 /* put zeros for variable based init */
8412 static void init_putz(CType
*t
, Section
*sec
, unsigned long c
, int size
)
8415 /* nothing to do because globals are already set to zero */
8417 vpush_global_sym(&func_old_type
, TOK_memset
);
8425 /* 't' contains the type and storage info. 'c' is the offset of the
8426 object in section 'sec'. If 'sec' is NULL, it means stack based
8427 allocation. 'first' is true if array '{' must be read (multi
8428 dimension implicit array init handling). 'size_only' is true if
8429 size only evaluation is wanted (only for arrays). */
8430 static void decl_initializer(CType
*type
, Section
*sec
, unsigned long c
,
8431 int first
, int size_only
)
8433 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
8434 int size1
, align1
, expr_type
;
8438 if (type
->t
& VT_ARRAY
) {
8442 t1
= pointed_type(type
);
8443 size1
= type_size(t1
, &align1
);
8446 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
8452 /* only parse strings here if correct type (otherwise: handle
8453 them as ((w)char *) expressions */
8454 if ((tok
== TOK_LSTR
&&
8455 #ifdef TCC_TARGET_PE
8456 (t1
->t
& VT_BTYPE
) == VT_SHORT
&& (t1
->t
& VT_UNSIGNED
)) ||
8458 (t1
->t
& VT_BTYPE
) == VT_INT
) ||
8461 (t1
->t
& VT_BTYPE
) == VT_BYTE
)) {
8462 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8467 /* compute maximum number of chars wanted */
8469 cstr_len
= cstr
->size
;
8471 cstr_len
= cstr
->size
/ sizeof(nwchar_t
);
8474 if (n
>= 0 && nb
> (n
- array_length
))
8475 nb
= n
- array_length
;
8478 warning("initializer-string for array is too long");
8479 /* in order to go faster for common case (char
8480 string in global variable, we handle it
8482 if (sec
&& tok
== TOK_STR
&& size1
== 1) {
8483 memcpy(sec
->data
+ c
+ array_length
, cstr
->data
, nb
);
8487 ch
= ((unsigned char *)cstr
->data
)[i
];
8489 ch
= ((nwchar_t
*)cstr
->data
)[i
];
8490 init_putv(t1
, sec
, c
+ (array_length
+ i
) * size1
,
8498 /* only add trailing zero if enough storage (no
8499 warning in this case since it is standard) */
8500 if (n
< 0 || array_length
< n
) {
8502 init_putv(t1
, sec
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
8508 while (tok
!= '}') {
8509 decl_designator(type
, sec
, c
, &index
, NULL
, size_only
);
8510 if (n
>= 0 && index
>= n
)
8511 error("index too large");
8512 /* must put zero in holes (note that doing it that way
8513 ensures that it even works with designators) */
8514 if (!size_only
&& array_length
< index
) {
8515 init_putz(t1
, sec
, c
+ array_length
* size1
,
8516 (index
- array_length
) * size1
);
8519 if (index
> array_length
)
8520 array_length
= index
;
8521 /* special test for multi dimensional arrays (may not
8522 be strictly correct if designators are used at the
8524 if (index
>= n
&& no_oblock
)
8533 /* put zeros at the end */
8534 if (!size_only
&& n
>= 0 && array_length
< n
) {
8535 init_putz(t1
, sec
, c
+ array_length
* size1
,
8536 (n
- array_length
) * size1
);
8538 /* patch type size if needed */
8540 s
->c
= array_length
;
8541 } else if ((type
->t
& VT_BTYPE
) == VT_STRUCT
&&
8542 (sec
|| !first
|| tok
== '{')) {
8545 /* NOTE: the previous test is a specific case for automatic
8546 struct/union init */
8547 /* XXX: union needs only one init */
8549 /* XXX: this test is incorrect for local initializers
8550 beginning with ( without {. It would be much more difficult
8551 to do it correctly (ideally, the expression parser should
8552 be used in all cases) */
8558 while (tok
== '(') {
8562 if (!parse_btype(&type1
, &ad1
))
8564 type_decl(&type1
, &ad1
, &n
, TYPE_ABSTRACT
);
8566 if (!is_assignable_types(type
, &type1
))
8567 error("invalid type for cast");
8572 if (first
|| tok
== '{') {
8581 while (tok
!= '}') {
8582 decl_designator(type
, sec
, c
, NULL
, &f
, size_only
);
8584 if (!size_only
&& array_length
< index
) {
8585 init_putz(type
, sec
, c
+ array_length
,
8586 index
- array_length
);
8588 index
= index
+ type_size(&f
->type
, &align1
);
8589 if (index
> array_length
)
8590 array_length
= index
;
8592 if (no_oblock
&& f
== NULL
)
8598 /* put zeros at the end */
8599 if (!size_only
&& array_length
< n
) {
8600 init_putz(type
, sec
, c
+ array_length
,
8609 } else if (tok
== '{') {
8611 decl_initializer(type
, sec
, c
, first
, size_only
);
8613 } else if (size_only
) {
8614 /* just skip expression */
8616 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
8620 else if (tok
== ')')
8625 /* currently, we always use constant expression for globals
8626 (may change for scripting case) */
8627 expr_type
= EXPR_CONST
;
8629 expr_type
= EXPR_ANY
;
8630 init_putv(type
, sec
, c
, 0, expr_type
);
8634 /* parse an initializer for type 't' if 'has_init' is non zero, and
8635 allocate space in local or global data space ('r' is either
8636 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8637 variable 'v' of scope 'scope' is declared before initializers are
8638 parsed. If 'v' is zero, then a reference to the new object is put
8639 in the value stack. If 'has_init' is 2, a special parsing is done
8640 to handle string constants. */
8641 static void decl_initializer_alloc(CType
*type
, AttributeDef
*ad
, int r
,
8642 int has_init
, int v
, int scope
)
8644 int size
, align
, addr
, data_offset
;
8646 ParseState saved_parse_state
;
8647 TokenString init_str
;
8650 size
= type_size(type
, &align
);
8651 /* If unknown size, we must evaluate it before
8652 evaluating initializers because
8653 initializers can generate global data too
8654 (e.g. string pointers or ISOC99 compound
8655 literals). It also simplifies local
8656 initializers handling */
8657 tok_str_new(&init_str
);
8660 error("unknown type size");
8661 /* get all init string */
8662 if (has_init
== 2) {
8663 /* only get strings */
8664 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
8665 tok_str_add_tok(&init_str
);
8670 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
8672 error("unexpected end of file in initializer");
8673 tok_str_add_tok(&init_str
);
8676 else if (tok
== '}') {
8684 tok_str_add(&init_str
, -1);
8685 tok_str_add(&init_str
, 0);
8688 save_parse_state(&saved_parse_state
);
8690 macro_ptr
= init_str
.str
;
8692 decl_initializer(type
, NULL
, 0, 1, 1);
8693 /* prepare second initializer parsing */
8694 macro_ptr
= init_str
.str
;
8697 /* if still unknown size, error */
8698 size
= type_size(type
, &align
);
8700 error("unknown type size");
8702 /* take into account specified alignment if bigger */
8704 if (ad
->aligned
> align
)
8705 align
= ad
->aligned
;
8706 } else if (ad
->packed
) {
8709 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
8711 if (do_bounds_check
&& (type
->t
& VT_ARRAY
))
8713 loc
= (loc
- size
) & -align
;
8715 /* handles bounds */
8716 /* XXX: currently, since we do only one pass, we cannot track
8717 '&' operators, so we add only arrays */
8718 if (do_bounds_check
&& (type
->t
& VT_ARRAY
)) {
8719 unsigned long *bounds_ptr
;
8720 /* add padding between regions */
8722 /* then add local bound info */
8723 bounds_ptr
= section_ptr_add(lbounds_section
, 2 * sizeof(unsigned long));
8724 bounds_ptr
[0] = addr
;
8725 bounds_ptr
[1] = size
;
8728 /* local variable */
8729 sym_push(v
, type
, r
, addr
);
8731 /* push local reference */
8732 vset(type
, r
, addr
);
8738 if (v
&& scope
== VT_CONST
) {
8739 /* see if the symbol was already defined */
8742 if (!is_compatible_types(&sym
->type
, type
))
8743 error("incompatible types for redefinition of '%s'",
8744 get_tok_str(v
, NULL
));
8745 if (sym
->type
.t
& VT_EXTERN
) {
8746 /* if the variable is extern, it was not allocated */
8747 sym
->type
.t
&= ~VT_EXTERN
;
8748 /* set array size if it was ommited in extern
8750 if ((sym
->type
.t
& VT_ARRAY
) &&
8751 sym
->type
.ref
->c
< 0 &&
8753 sym
->type
.ref
->c
= type
->ref
->c
;
8755 /* we accept several definitions of the same
8756 global variable. this is tricky, because we
8757 must play with the SHN_COMMON type of the symbol */
8758 /* XXX: should check if the variable was already
8759 initialized. It is incorrect to initialized it
8761 /* no init data, we won't add more to the symbol */
8768 /* allocate symbol in corresponding section */
8773 else if (tcc_state
->nocommon
)
8777 data_offset
= sec
->data_offset
;
8778 data_offset
= (data_offset
+ align
- 1) & -align
;
8780 /* very important to increment global pointer at this time
8781 because initializers themselves can create new initializers */
8782 data_offset
+= size
;
8783 /* add padding if bound check */
8784 if (do_bounds_check
)
8786 sec
->data_offset
= data_offset
;
8787 /* allocate section space to put the data */
8788 if (sec
->sh_type
!= SHT_NOBITS
&&
8789 data_offset
> sec
->data_allocated
)
8790 section_realloc(sec
, data_offset
);
8791 /* align section if needed */
8792 if (align
> sec
->sh_addralign
)
8793 sec
->sh_addralign
= align
;
8795 addr
= 0; /* avoid warning */
8799 if (scope
== VT_CONST
) {
8804 sym
= sym_push(v
, type
, r
| VT_SYM
, 0);
8806 /* update symbol definition */
8808 put_extern_sym(sym
, sec
, addr
, size
);
8811 /* put a common area */
8812 put_extern_sym(sym
, NULL
, align
, size
);
8813 /* XXX: find a nicer way */
8814 esym
= &((Elf32_Sym
*)symtab_section
->data
)[sym
->c
];
8815 esym
->st_shndx
= SHN_COMMON
;
8820 /* push global reference */
8821 sym
= get_sym_ref(type
, sec
, addr
, size
);
8823 vsetc(type
, VT_CONST
| VT_SYM
, &cval
);
8827 /* handles bounds now because the symbol must be defined
8828 before for the relocation */
8829 if (do_bounds_check
) {
8830 unsigned long *bounds_ptr
;
8832 greloc(bounds_section
, sym
, bounds_section
->data_offset
, R_DATA_32
);
8833 /* then add global bound info */
8834 bounds_ptr
= section_ptr_add(bounds_section
, 2 * sizeof(long));
8835 bounds_ptr
[0] = 0; /* relocated */
8836 bounds_ptr
[1] = size
;
8840 decl_initializer(type
, sec
, addr
, 1, 0);
8841 /* restore parse state if needed */
8843 tok_str_free(init_str
.str
);
8844 restore_parse_state(&saved_parse_state
);
8850 void put_func_debug(Sym
*sym
)
8855 /* XXX: we put here a dummy type */
8856 snprintf(buf
, sizeof(buf
), "%s:%c1",
8857 funcname
, sym
->type
.t
& VT_STATIC
? 'f' : 'F');
8858 put_stabs_r(buf
, N_FUN
, 0, file
->line_num
, 0,
8859 cur_text_section
, sym
->c
);
8864 /* parse an old style function declaration list */
8865 /* XXX: check multiple parameter */
8866 static void func_decl_list(Sym
*func_sym
)
8873 /* parse each declaration */
8874 while (tok
!= '{' && tok
!= ';' && tok
!= ',' && tok
!= TOK_EOF
) {
8875 if (!parse_btype(&btype
, &ad
))
8876 expect("declaration list");
8877 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
8878 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
8880 /* we accept no variable after */
8884 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
8885 /* find parameter in function parameter list */
8888 if ((s
->v
& ~SYM_FIELD
) == v
)
8892 error("declaration for parameter '%s' but no such parameter",
8893 get_tok_str(v
, NULL
));
8895 /* check that no storage specifier except 'register' was given */
8896 if (type
.t
& VT_STORAGE
)
8897 error("storage class specified for '%s'", get_tok_str(v
, NULL
));
8898 convert_parameter_type(&type
);
8899 /* we can add the type (NOTE: it could be local to the function) */
8901 /* accept other parameters */
8912 /* parse a function defined by symbol 'sym' and generate its code in
8913 'cur_text_section' */
8914 static void gen_function(Sym
*sym
)
8916 ind
= cur_text_section
->data_offset
;
8917 /* NOTE: we patch the symbol size later */
8918 put_extern_sym(sym
, cur_text_section
, ind
, 0);
8919 funcname
= get_tok_str(sym
->v
, NULL
);
8921 /* put debug symbol */
8923 put_func_debug(sym
);
8924 /* push a dummy symbol to enable local sym storage */
8925 sym_push2(&local_stack
, SYM_FIELD
, 0, 0);
8926 gfunc_prolog(&sym
->type
);
8928 block(NULL
, NULL
, NULL
, NULL
, 0, 0);
8931 cur_text_section
->data_offset
= ind
;
8932 label_pop(&global_label_stack
, NULL
);
8933 sym_pop(&local_stack
, NULL
); /* reset local stack */
8934 /* end of function */
8935 /* patch symbol size */
8936 ((Elf32_Sym
*)symtab_section
->data
)[sym
->c
].st_size
=
8939 put_stabn(N_FUN
, 0, 0, ind
- func_ind
);
8941 funcname
= ""; /* for safety */
8942 func_vt
.t
= VT_VOID
; /* for safety */
8943 ind
= 0; /* for safety */
8946 static void gen_inline_functions(void)
8950 int *str
, inline_generated
;
8952 /* iterate while inline function are referenced */
8954 inline_generated
= 0;
8955 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
8957 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
8958 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
8959 (VT_STATIC
| VT_INLINE
) &&
8961 /* the function was used: generate its code and
8962 convert it to a normal function */
8963 str
= (int *)sym
->r
;
8964 sym
->r
= VT_SYM
| VT_CONST
;
8965 type
->t
&= ~VT_INLINE
;
8969 cur_text_section
= text_section
;
8971 macro_ptr
= NULL
; /* fail safe */
8974 inline_generated
= 1;
8977 if (!inline_generated
)
8981 /* free all remaining inline function tokens */
8982 for(sym
= global_stack
; sym
!= NULL
; sym
= sym
->prev
) {
8984 if (((type
->t
& VT_BTYPE
) == VT_FUNC
) &&
8985 (type
->t
& (VT_STATIC
| VT_INLINE
)) ==
8986 (VT_STATIC
| VT_INLINE
)) {
8987 str
= (int *)sym
->r
;
8989 sym
->r
= 0; /* fail safe */
8994 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
8995 static void decl(int l
)
9003 if (!parse_btype(&btype
, &ad
)) {
9004 /* skip redundant ';' */
9005 /* XXX: find more elegant solution */
9010 if (l
== VT_CONST
&&
9011 (tok
== TOK_ASM1
|| tok
== TOK_ASM2
|| tok
== TOK_ASM3
)) {
9012 /* global asm block */
9016 /* special test for old K&R protos without explicit int
9017 type. Only accepted when defining global data */
9018 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
9022 if (((btype
.t
& VT_BTYPE
) == VT_ENUM
||
9023 (btype
.t
& VT_BTYPE
) == VT_STRUCT
) &&
9025 /* we accept no variable after */
9029 while (1) { /* iterate thru each declaration */
9031 type_decl(&type
, &ad
, &v
, TYPE_DIRECT
);
9035 type_to_str(buf
, sizeof(buf
), &type
, get_tok_str(v
, NULL
));
9036 printf("type = '%s'\n", buf
);
9039 if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9040 /* if old style function prototype, we accept a
9043 if (sym
->c
== FUNC_OLD
)
9044 func_decl_list(sym
);
9049 error("cannot use local functions");
9050 if ((type
.t
& VT_BTYPE
) != VT_FUNC
)
9051 expect("function definition");
9053 /* reject abstract declarators in function definition */
9055 while ((sym
= sym
->next
) != NULL
)
9056 if (!(sym
->v
& ~SYM_FIELD
))
9057 expect("identifier");
9059 /* XXX: cannot do better now: convert extern line to static inline */
9060 if ((type
.t
& (VT_EXTERN
| VT_INLINE
)) == (VT_EXTERN
| VT_INLINE
))
9061 type
.t
= (type
.t
& ~VT_EXTERN
) | VT_STATIC
;
9065 if ((sym
->type
.t
& VT_BTYPE
) != VT_FUNC
)
9067 /* specific case: if not func_call defined, we put
9068 the one of the prototype */
9069 /* XXX: should have default value */
9070 if (sym
->type
.ref
->r
!= FUNC_CDECL
&&
9071 type
.ref
->r
== FUNC_CDECL
)
9072 type
.ref
->r
= sym
->type
.ref
->r
;
9073 if (!is_compatible_types(&sym
->type
, &type
)) {
9075 error("incompatible types for redefinition of '%s'",
9076 get_tok_str(v
, NULL
));
9078 /* if symbol is already defined, then put complete type */
9081 /* put function symbol */
9082 sym
= global_identifier_push(v
, type
.t
, 0);
9083 sym
->type
.ref
= type
.ref
;
9086 /* static inline functions are just recorded as a kind
9087 of macro. Their code will be emitted at the end of
9088 the compilation unit only if they are used */
9089 if ((type
.t
& (VT_INLINE
| VT_STATIC
)) ==
9090 (VT_INLINE
| VT_STATIC
)) {
9091 TokenString func_str
;
9094 tok_str_new(&func_str
);
9100 error("unexpected end of file");
9101 tok_str_add_tok(&func_str
);
9106 } else if (t
== '}') {
9108 if (block_level
== 0)
9112 tok_str_add(&func_str
, -1);
9113 tok_str_add(&func_str
, 0);
9114 sym
->r
= (int)func_str
.str
;
9116 /* compute text section */
9117 cur_text_section
= ad
.section
;
9118 if (!cur_text_section
)
9119 cur_text_section
= text_section
;
9120 sym
->r
= VT_SYM
| VT_CONST
;
9122 #ifdef TCC_TARGET_PE
9124 ((Elf32_Sym
*)symtab_section
->data
)[sym
->c
].st_other
|= 1;
9130 if (btype
.t
& VT_TYPEDEF
) {
9131 /* save typedefed type */
9132 /* XXX: test storage specifiers ? */
9133 sym
= sym_push(v
, &type
, 0, 0);
9134 sym
->type
.t
|= VT_TYPEDEF
;
9135 } else if ((type
.t
& VT_BTYPE
) == VT_FUNC
) {
9136 /* external function definition */
9137 /* specific case for func_call attribute */
9139 type
.ref
->r
= ad
.func_call
;
9140 external_sym(v
, &type
, 0);
9142 /* not lvalue if array */
9144 if (!(type
.t
& VT_ARRAY
))
9145 r
|= lvalue_type(type
.t
);
9146 has_init
= (tok
== '=');
9147 if ((btype
.t
& VT_EXTERN
) ||
9148 ((type
.t
& VT_ARRAY
) && (type
.t
& VT_STATIC
) &&
9149 !has_init
&& l
== VT_CONST
&& type
.ref
->c
< 0)) {
9150 /* external variable */
9151 /* NOTE: as GCC, uninitialized global static
9152 arrays of null size are considered as
9154 external_sym(v
, &type
, r
);
9156 if (type
.t
& VT_STATIC
)
9162 decl_initializer_alloc(&type
, &ad
, r
,
9176 /* better than nothing, but needs extension to handle '-E' option
9178 static void preprocess_init(TCCState
*s1
)
9180 s1
->include_stack_ptr
= s1
->include_stack
;
9181 /* XXX: move that before to avoid having to initialize
9182 file->ifdef_stack_ptr ? */
9183 s1
->ifdef_stack_ptr
= s1
->ifdef_stack
;
9184 file
->ifdef_stack_ptr
= s1
->ifdef_stack_ptr
;
9186 /* XXX: not ANSI compliant: bound checking says error */
9188 s1
->pack_stack
[0] = 0;
9189 s1
->pack_stack_ptr
= s1
->pack_stack
;
9192 /* compile the C file opened in 'file'. Return non zero if errors. */
9193 static int tcc_compile(TCCState
*s1
)
9197 volatile int section_sym
;
9200 printf("%s: **** new file\n", file
->filename
);
9202 preprocess_init(s1
);
9205 anon_sym
= SYM_FIRST_ANOM
;
9207 /* file info: full path + filename */
9208 section_sym
= 0; /* avoid warning */
9210 section_sym
= put_elf_sym(symtab_section
, 0, 0,
9211 ELF32_ST_INFO(STB_LOCAL
, STT_SECTION
), 0,
9212 text_section
->sh_num
, NULL
);
9213 getcwd(buf
, sizeof(buf
));
9214 pstrcat(buf
, sizeof(buf
), "/");
9215 put_stabs_r(buf
, N_SO
, 0, 0,
9216 text_section
->data_offset
, text_section
, section_sym
);
9217 put_stabs_r(file
->filename
, N_SO
, 0, 0,
9218 text_section
->data_offset
, text_section
, section_sym
);
9220 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9221 symbols can be safely used */
9222 put_elf_sym(symtab_section
, 0, 0,
9223 ELF32_ST_INFO(STB_LOCAL
, STT_FILE
), 0,
9224 SHN_ABS
, file
->filename
);
9226 /* define some often used types */
9227 int_type
.t
= VT_INT
;
9229 char_pointer_type
.t
= VT_BYTE
;
9230 mk_pointer(&char_pointer_type
);
9232 func_old_type
.t
= VT_FUNC
;
9233 func_old_type
.ref
= sym_push(SYM_FIELD
, &int_type
, FUNC_CDECL
, FUNC_OLD
);
9236 /* define 'void *alloca(unsigned int)' builtin function */
9241 sym
= sym_push(p
, mk_pointer(VT_VOID
), FUNC_CDECL
, FUNC_NEW
);
9242 s1
= sym_push(SYM_FIELD
, VT_UNSIGNED
| VT_INT
, 0, 0);
9245 sym_push(TOK_alloca
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), VT_CONST
, 0);
9249 define_start
= define_stack
;
9251 if (setjmp(s1
->error_jmp_buf
) == 0) {
9253 s1
->error_set_jmp_enabled
= 1;
9255 ch
= file
->buf_ptr
[0];
9256 tok_flags
= TOK_FLAG_BOL
| TOK_FLAG_BOF
;
9257 parse_flags
= PARSE_FLAG_PREPROCESS
| PARSE_FLAG_TOK_NUM
;
9261 expect("declaration");
9263 /* end of translation unit info */
9265 put_stabs_r(NULL
, N_SO
, 0, 0,
9266 text_section
->data_offset
, text_section
, section_sym
);
9269 s1
->error_set_jmp_enabled
= 0;
9271 /* reset define stack, but leave -Dsymbols (may be incorrect if
9272 they are undefined) */
9273 free_defines(define_start
);
9275 gen_inline_functions();
9277 sym_pop(&global_stack
, NULL
);
9279 return s1
->nb_errors
!= 0 ? -1 : 0;
9283 int tcc_compile_string(TCCState
*s
, const char *str
)
9285 BufferedFile bf1
, *bf
= &bf1
;
9289 /* init file structure */
9291 /* XXX: avoid copying */
9293 buf
= tcc_malloc(len
+ 1);
9296 memcpy(buf
, str
, len
);
9299 bf
->buf_end
= buf
+ len
;
9300 pstrcpy(bf
->filename
, sizeof(bf
->filename
), "<string>");
9304 ret
= tcc_compile(s
);
9308 /* currently, no need to close */
9313 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
9314 void tcc_define_symbol(TCCState
*s1
, const char *sym
, const char *value
)
9316 BufferedFile bf1
, *bf
= &bf1
;
9318 pstrcpy(bf
->buffer
, IO_BUF_SIZE
, sym
);
9319 pstrcat(bf
->buffer
, IO_BUF_SIZE
, " ");
9323 pstrcat(bf
->buffer
, IO_BUF_SIZE
, value
);
9325 /* init file structure */
9327 bf
->buf_ptr
= bf
->buffer
;
9328 bf
->buf_end
= bf
->buffer
+ strlen(bf
->buffer
);
9329 *bf
->buf_end
= CH_EOB
;
9330 bf
->filename
[0] = '\0';
9334 s1
->include_stack_ptr
= s1
->include_stack
;
9336 /* parse with define parser */
9337 ch
= file
->buf_ptr
[0];
9343 /* undefine a preprocessor symbol */
9344 void tcc_undefine_symbol(TCCState
*s1
, const char *sym
)
9348 ts
= tok_alloc(sym
, strlen(sym
));
9349 s
= define_find(ts
->tok
);
9350 /* undefine symbol by putting an invalid name */
9355 #ifdef CONFIG_TCC_ASM
9357 #ifdef TCC_TARGET_I386
9358 #include "i386-asm.c"
9363 static void asm_instr(void)
9365 error("inline asm() not supported");
9367 static void asm_global_instr(void)
9369 error("inline asm() not supported");
9375 #ifdef TCC_TARGET_COFF
9376 #include "tcccoff.c"
9379 #ifdef TCC_TARGET_PE
9383 /* print the position in the source file of PC value 'pc' by reading
9384 the stabs debug information */
9385 static void rt_printline(unsigned long wanted_pc
)
9387 Stab_Sym
*sym
, *sym_end
;
9388 char func_name
[128], last_func_name
[128];
9389 unsigned long func_addr
, last_pc
, pc
;
9390 const char *incl_files
[INCLUDE_STACK_SIZE
];
9391 int incl_index
, len
, last_line_num
, i
;
9392 const char *str
, *p
;
9394 fprintf(stderr
, "0x%08lx:", wanted_pc
);
9396 func_name
[0] = '\0';
9399 last_func_name
[0] = '\0';
9400 last_pc
= 0xffffffff;
9402 sym
= (Stab_Sym
*)stab_section
->data
+ 1;
9403 sym_end
= (Stab_Sym
*)(stab_section
->data
+ stab_section
->data_offset
);
9404 while (sym
< sym_end
) {
9405 switch(sym
->n_type
) {
9406 /* function start or end */
9408 if (sym
->n_strx
== 0) {
9409 /* we test if between last line and end of function */
9410 pc
= sym
->n_value
+ func_addr
;
9411 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
9413 func_name
[0] = '\0';
9416 str
= stabstr_section
->data
+ sym
->n_strx
;
9417 p
= strchr(str
, ':');
9419 pstrcpy(func_name
, sizeof(func_name
), str
);
9422 if (len
> sizeof(func_name
) - 1)
9423 len
= sizeof(func_name
) - 1;
9424 memcpy(func_name
, str
, len
);
9425 func_name
[len
] = '\0';
9427 func_addr
= sym
->n_value
;
9430 /* line number info */
9432 pc
= sym
->n_value
+ func_addr
;
9433 if (wanted_pc
>= last_pc
&& wanted_pc
< pc
)
9436 last_line_num
= sym
->n_desc
;
9438 strcpy(last_func_name
, func_name
);
9442 str
= stabstr_section
->data
+ sym
->n_strx
;
9444 if (incl_index
< INCLUDE_STACK_SIZE
) {
9445 incl_files
[incl_index
++] = str
;
9453 if (sym
->n_strx
== 0) {
9454 incl_index
= 0; /* end of translation unit */
9456 str
= stabstr_section
->data
+ sym
->n_strx
;
9457 /* do not add path */
9459 if (len
> 0 && str
[len
- 1] != '/')
9467 /* second pass: we try symtab symbols (no line number info) */
9470 Elf32_Sym
*sym
, *sym_end
;
9473 sym_end
= (Elf32_Sym
*)(symtab_section
->data
+ symtab_section
->data_offset
);
9474 for(sym
= (Elf32_Sym
*)symtab_section
->data
+ 1;
9477 type
= ELF32_ST_TYPE(sym
->st_info
);
9478 if (type
== STT_FUNC
) {
9479 if (wanted_pc
>= sym
->st_value
&&
9480 wanted_pc
< sym
->st_value
+ sym
->st_size
) {
9481 pstrcpy(last_func_name
, sizeof(last_func_name
),
9482 strtab_section
->data
+ sym
->st_name
);
9488 /* did not find any info: */
9489 fprintf(stderr
, " ???\n");
9492 if (last_func_name
[0] != '\0') {
9493 fprintf(stderr
, " %s()", last_func_name
);
9495 if (incl_index
> 0) {
9496 fprintf(stderr
, " (%s:%d",
9497 incl_files
[incl_index
- 1], last_line_num
);
9498 for(i
= incl_index
- 2; i
>= 0; i
--)
9499 fprintf(stderr
, ", included from %s", incl_files
[i
]);
9500 fprintf(stderr
, ")");
9502 fprintf(stderr
, "\n");
9505 #if !defined(WIN32) && !defined(CONFIG_TCCBOOT)
9509 /* fix for glibc 2.1 */
9515 /* return the PC at frame level 'level'. Return non zero if not found */
9516 static int rt_get_caller_pc(unsigned long *paddr
,
9517 ucontext_t
*uc
, int level
)
9523 #if defined(__FreeBSD__)
9524 *paddr
= uc
->uc_mcontext
.mc_eip
;
9525 #elif defined(__dietlibc__)
9526 *paddr
= uc
->uc_mcontext
.eip
;
9528 *paddr
= uc
->uc_mcontext
.gregs
[REG_EIP
];
9532 #if defined(__FreeBSD__)
9533 fp
= uc
->uc_mcontext
.mc_ebp
;
9534 #elif defined(__dietlibc__)
9535 fp
= uc
->uc_mcontext
.ebp
;
9537 fp
= uc
->uc_mcontext
.gregs
[REG_EBP
];
9539 for(i
=1;i
<level
;i
++) {
9540 /* XXX: check address validity with program info */
9541 if (fp
<= 0x1000 || fp
>= 0xc0000000)
9543 fp
= ((unsigned long *)fp
)[0];
9545 *paddr
= ((unsigned long *)fp
)[1];
9551 #warning add arch specific rt_get_caller_pc()
9553 static int rt_get_caller_pc(unsigned long *paddr
,
9554 ucontext_t
*uc
, int level
)
9560 /* emit a run time error at position 'pc' */
9561 void rt_error(ucontext_t
*uc
, const char *fmt
, ...)
9568 fprintf(stderr
, "Runtime error: ");
9569 vfprintf(stderr
, fmt
, ap
);
9570 fprintf(stderr
, "\n");
9571 for(i
=0;i
<num_callers
;i
++) {
9572 if (rt_get_caller_pc(&pc
, uc
, i
) < 0)
9575 fprintf(stderr
, "at ");
9577 fprintf(stderr
, "by ");
9584 /* signal handler for fatal errors */
9585 static void sig_error(int signum
, siginfo_t
*siginf
, void *puc
)
9587 ucontext_t
*uc
= puc
;
9591 switch(siginf
->si_code
) {
9594 rt_error(uc
, "division by zero");
9597 rt_error(uc
, "floating point exception");
9603 if (rt_bound_error_msg
&& *rt_bound_error_msg
)
9604 rt_error(uc
, *rt_bound_error_msg
);
9606 rt_error(uc
, "dereferencing invalid pointer");
9609 rt_error(uc
, "illegal instruction");
9612 rt_error(uc
, "abort() called");
9615 rt_error(uc
, "caught signal %d", signum
);
9622 /* do all relocations (needed before using tcc_get_symbol()) */
9623 int tcc_relocate(TCCState
*s1
)
9630 #ifdef TCC_TARGET_PE
9633 tcc_add_runtime(s1
);
9636 relocate_common_syms();
9638 tcc_add_linker_symbols(s1
);
9640 build_got_entries(s1
);
9642 /* compute relocation address : section are relocated in place. We
9643 also alloc the bss space */
9644 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9645 s
= s1
->sections
[i
];
9646 if (s
->sh_flags
& SHF_ALLOC
) {
9647 if (s
->sh_type
== SHT_NOBITS
)
9648 s
->data
= tcc_mallocz(s
->data_offset
);
9649 s
->sh_addr
= (unsigned long)s
->data
;
9653 relocate_syms(s1
, 1);
9655 if (s1
->nb_errors
!= 0)
9658 /* relocate each section */
9659 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9660 s
= s1
->sections
[i
];
9662 relocate_section(s1
, s
);
9665 /* mark executable sections as executable in memory */
9666 for(i
= 1; i
< s1
->nb_sections
; i
++) {
9667 s
= s1
->sections
[i
];
9668 if ((s
->sh_flags
& (SHF_ALLOC
| SHF_EXECINSTR
)) ==
9669 (SHF_ALLOC
| SHF_EXECINSTR
)) {
9673 VirtualProtect(s
->data
, s
->data_offset
,
9674 PAGE_EXECUTE_READWRITE
, &old_protect
);
9678 unsigned long start
, end
;
9679 start
= (unsigned long)(s
->data
) & ~(PAGESIZE
- 1);
9680 end
= (unsigned long)(s
->data
+ s
->data_offset
);
9681 end
= (end
+ PAGESIZE
- 1) & ~(PAGESIZE
- 1);
9682 mprotect((void *)start
, end
- start
,
9683 PROT_READ
| PROT_WRITE
| PROT_EXEC
);
9691 /* launch the compiled program with the given arguments */
9692 int tcc_run(TCCState
*s1
, int argc
, char **argv
)
9694 int (*prog_main
)(int, char **);
9696 if (tcc_relocate(s1
) < 0)
9699 prog_main
= tcc_get_symbol_err(s1
, "main");
9702 #if defined(WIN32) || defined(CONFIG_TCCBOOT)
9703 error("debug mode currently not available for Windows");
9705 struct sigaction sigact
;
9706 /* install TCC signal handlers to print debug info on fatal
9708 sigact
.sa_flags
= SA_SIGINFO
| SA_RESETHAND
;
9709 sigact
.sa_sigaction
= sig_error
;
9710 sigemptyset(&sigact
.sa_mask
);
9711 sigaction(SIGFPE
, &sigact
, NULL
);
9712 sigaction(SIGILL
, &sigact
, NULL
);
9713 sigaction(SIGSEGV
, &sigact
, NULL
);
9714 sigaction(SIGBUS
, &sigact
, NULL
);
9715 sigaction(SIGABRT
, &sigact
, NULL
);
9719 #ifdef CONFIG_TCC_BCHECK
9720 if (do_bounds_check
) {
9721 void (*bound_init
)(void);
9723 /* set error function */
9724 rt_bound_error_msg
= (void *)tcc_get_symbol_err(s1
,
9725 "__bound_error_msg");
9727 /* XXX: use .init section so that it also work in binary ? */
9728 bound_init
= (void *)tcc_get_symbol_err(s1
, "__bound_init");
9732 return (*prog_main
)(argc
, argv
);
9735 TCCState
*tcc_new(void)
9742 s
= tcc_mallocz(sizeof(TCCState
));
9746 s
->output_type
= TCC_OUTPUT_MEMORY
;
9748 /* init isid table */
9750 isidnum_table
[i
] = isid(i
) || isnum(i
);
9752 /* add all tokens */
9754 memset(hash_ident
, 0, TOK_HASH_SIZE
* sizeof(TokenSym
*));
9756 tok_ident
= TOK_IDENT
;
9765 ts
= tok_alloc(p
, r
- p
- 1);
9769 /* we add dummy defines for some special macros to speed up tests
9770 and to have working defined() */
9771 define_push(TOK___LINE__
, MACRO_OBJ
, NULL
, NULL
);
9772 define_push(TOK___FILE__
, MACRO_OBJ
, NULL
, NULL
);
9773 define_push(TOK___DATE__
, MACRO_OBJ
, NULL
, NULL
);
9774 define_push(TOK___TIME__
, MACRO_OBJ
, NULL
, NULL
);
9776 /* standard defines */
9777 tcc_define_symbol(s
, "__STDC__", NULL
);
9778 #if defined(TCC_TARGET_I386)
9779 tcc_define_symbol(s
, "__i386__", NULL
);
9781 #if defined(TCC_TARGET_ARM)
9782 tcc_define_symbol(s
, "__ARM_ARCH_4__", NULL
);
9783 tcc_define_symbol(s
, "__arm_elf__", NULL
);
9784 tcc_define_symbol(s
, "__arm_elf", NULL
);
9785 tcc_define_symbol(s
, "arm_elf", NULL
);
9786 tcc_define_symbol(s
, "__arm__", NULL
);
9787 tcc_define_symbol(s
, "__arm", NULL
);
9788 tcc_define_symbol(s
, "arm", NULL
);
9789 tcc_define_symbol(s
, "__APCS_32__", NULL
);
9792 tcc_define_symbol(s
, "__linux__", NULL
);
9793 tcc_define_symbol(s
, "linux", NULL
);
9795 /* tiny C specific defines */
9796 tcc_define_symbol(s
, "__TINYC__", NULL
);
9798 /* tiny C & gcc defines */
9799 tcc_define_symbol(s
, "__SIZE_TYPE__", "unsigned int");
9800 tcc_define_symbol(s
, "__PTRDIFF_TYPE__", "int");
9801 #ifdef TCC_TARGET_PE
9802 tcc_define_symbol(s
, "__WCHAR_TYPE__", "unsigned short");
9804 tcc_define_symbol(s
, "__WCHAR_TYPE__", "int");
9807 /* default library paths */
9808 #ifdef TCC_TARGET_PE
9811 snprintf(buf
, sizeof(buf
), "%s/lib", tcc_lib_path
);
9812 tcc_add_library_path(s
, buf
);
9815 tcc_add_library_path(s
, "/usr/local/lib");
9816 tcc_add_library_path(s
, "/usr/lib");
9817 tcc_add_library_path(s
, "/lib");
9820 /* no section zero */
9821 dynarray_add((void ***)&s
->sections
, &s
->nb_sections
, NULL
);
9823 /* create standard sections */
9824 text_section
= new_section(s
, ".text", SHT_PROGBITS
, SHF_ALLOC
| SHF_EXECINSTR
);
9825 data_section
= new_section(s
, ".data", SHT_PROGBITS
, SHF_ALLOC
| SHF_WRITE
);
9826 bss_section
= new_section(s
, ".bss", SHT_NOBITS
, SHF_ALLOC
| SHF_WRITE
);
9828 /* symbols are always generated for linking stage */
9829 symtab_section
= new_symtab(s
, ".symtab", SHT_SYMTAB
, 0,
9831 ".hashtab", SHF_PRIVATE
);
9832 strtab_section
= symtab_section
->link
;
9834 /* private symbol table for dynamic symbols */
9835 s
->dynsymtab_section
= new_symtab(s
, ".dynsymtab", SHT_SYMTAB
, SHF_PRIVATE
,
9837 ".dynhashtab", SHF_PRIVATE
);
9838 s
->alacarte_link
= 1;
9840 #ifdef CHAR_IS_UNSIGNED
9841 s
->char_is_unsigned
= 1;
9843 #if defined(TCC_TARGET_PE) && 0
9844 /* XXX: currently the PE linker is not ready to support that */
9845 s
->leading_underscore
= 1;
9850 void tcc_delete(TCCState
*s1
)
9854 /* free -D defines */
9858 n
= tok_ident
- TOK_IDENT
;
9859 for(i
= 0; i
< n
; i
++)
9860 tcc_free(table_ident
[i
]);
9861 tcc_free(table_ident
);
9863 /* free all sections */
9865 free_section(symtab_section
->hash
);
9867 free_section(s1
->dynsymtab_section
->hash
);
9868 free_section(s1
->dynsymtab_section
->link
);
9869 free_section(s1
->dynsymtab_section
);
9871 for(i
= 1; i
< s1
->nb_sections
; i
++)
9872 free_section(s1
->sections
[i
]);
9873 tcc_free(s1
->sections
);
9875 /* free loaded dlls array */
9876 for(i
= 0; i
< s1
->nb_loaded_dlls
; i
++)
9877 tcc_free(s1
->loaded_dlls
[i
]);
9878 tcc_free(s1
->loaded_dlls
);
9881 for(i
= 0; i
< s1
->nb_library_paths
; i
++)
9882 tcc_free(s1
->library_paths
[i
]);
9883 tcc_free(s1
->library_paths
);
9885 /* cached includes */
9886 for(i
= 0; i
< s1
->nb_cached_includes
; i
++)
9887 tcc_free(s1
->cached_includes
[i
]);
9888 tcc_free(s1
->cached_includes
);
9890 for(i
= 0; i
< s1
->nb_include_paths
; i
++)
9891 tcc_free(s1
->include_paths
[i
]);
9892 tcc_free(s1
->include_paths
);
9894 for(i
= 0; i
< s1
->nb_sysinclude_paths
; i
++)
9895 tcc_free(s1
->sysinclude_paths
[i
]);
9896 tcc_free(s1
->sysinclude_paths
);
9901 int tcc_add_include_path(TCCState
*s1
, const char *pathname
)
9905 pathname1
= tcc_strdup(pathname
);
9906 dynarray_add((void ***)&s1
->include_paths
, &s1
->nb_include_paths
, pathname1
);
9910 int tcc_add_sysinclude_path(TCCState
*s1
, const char *pathname
)
9914 pathname1
= tcc_strdup(pathname
);
9915 dynarray_add((void ***)&s1
->sysinclude_paths
, &s1
->nb_sysinclude_paths
, pathname1
);
9919 static int tcc_add_file_internal(TCCState
*s1
, const char *filename
, int flags
)
9921 const char *ext
, *filename1
;
9924 BufferedFile
*saved_file
;
9926 /* find source file type with extension */
9927 filename1
= strrchr(filename
, '/');
9931 filename1
= filename
;
9932 ext
= strrchr(filename1
, '.');
9938 file
= tcc_open(s1
, filename
);
9940 if (flags
& AFF_PRINT_ERROR
) {
9941 error_noabort("file '%s' not found", filename
);
9947 if (!ext
|| !strcmp(ext
, "c")) {
9948 /* C file assumed */
9949 ret
= tcc_compile(s1
);
9951 #ifdef CONFIG_TCC_ASM
9952 if (!strcmp(ext
, "S")) {
9953 /* preprocessed assembler */
9954 ret
= tcc_assemble(s1
, 1);
9955 } else if (!strcmp(ext
, "s")) {
9956 /* non preprocessed assembler */
9957 ret
= tcc_assemble(s1
, 0);
9960 #ifdef TCC_TARGET_PE
9961 if (!strcmp(ext
, "def")) {
9962 ret
= pe_load_def_file(s1
, fdopen(file
->fd
, "rb"));
9967 /* assume executable format: auto guess file type */
9968 ret
= read(fd
, &ehdr
, sizeof(ehdr
));
9969 lseek(fd
, 0, SEEK_SET
);
9971 error_noabort("could not read header");
9973 } else if (ret
!= sizeof(ehdr
)) {
9974 goto try_load_script
;
9977 if (ehdr
.e_ident
[0] == ELFMAG0
&&
9978 ehdr
.e_ident
[1] == ELFMAG1
&&
9979 ehdr
.e_ident
[2] == ELFMAG2
&&
9980 ehdr
.e_ident
[3] == ELFMAG3
) {
9981 file
->line_num
= 0; /* do not display line number if error */
9982 if (ehdr
.e_type
== ET_REL
) {
9983 ret
= tcc_load_object_file(s1
, fd
, 0);
9984 } else if (ehdr
.e_type
== ET_DYN
) {
9985 if (s1
->output_type
== TCC_OUTPUT_MEMORY
) {
9986 #ifdef TCC_TARGET_PE
9990 h
= dlopen(filename
, RTLD_GLOBAL
| RTLD_LAZY
);
9997 ret
= tcc_load_dll(s1
, fd
, filename
,
9998 (flags
& AFF_REFERENCED_DLL
) != 0);
10001 error_noabort("unrecognized ELF file");
10004 } else if (memcmp((char *)&ehdr
, ARMAG
, 8) == 0) {
10005 file
->line_num
= 0; /* do not display line number if error */
10006 ret
= tcc_load_archive(s1
, fd
);
10008 #ifdef TCC_TARGET_COFF
10009 if (*(uint16_t *)(&ehdr
) == COFF_C67_MAGIC
) {
10010 ret
= tcc_load_coff(s1
, fd
);
10014 /* as GNU ld, consider it is an ld script if not recognized */
10016 ret
= tcc_load_ldscript(s1
);
10018 error_noabort("unrecognized file type");
10033 int tcc_add_file(TCCState
*s
, const char *filename
)
10035 return tcc_add_file_internal(s
, filename
, AFF_PRINT_ERROR
);
10038 int tcc_add_library_path(TCCState
*s
, const char *pathname
)
10042 pathname1
= tcc_strdup(pathname
);
10043 dynarray_add((void ***)&s
->library_paths
, &s
->nb_library_paths
, pathname1
);
10047 /* find and load a dll. Return non zero if not found */
10048 /* XXX: add '-rpath' option support ? */
10049 static int tcc_add_dll(TCCState
*s
, const char *filename
, int flags
)
10054 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
10055 snprintf(buf
, sizeof(buf
), "%s/%s",
10056 s
->library_paths
[i
], filename
);
10057 if (tcc_add_file_internal(s
, buf
, flags
) == 0)
10063 /* the library name is the same as the argument of the '-l' option */
10064 int tcc_add_library(TCCState
*s
, const char *libraryname
)
10069 /* first we look for the dynamic library if not static linking */
10070 if (!s
->static_link
) {
10071 #ifdef TCC_TARGET_PE
10072 snprintf(buf
, sizeof(buf
), "%s.def", libraryname
);
10074 snprintf(buf
, sizeof(buf
), "lib%s.so", libraryname
);
10076 if (tcc_add_dll(s
, buf
, 0) == 0)
10080 /* then we look for the static library */
10081 for(i
= 0; i
< s
->nb_library_paths
; i
++) {
10082 snprintf(buf
, sizeof(buf
), "%s/lib%s.a",
10083 s
->library_paths
[i
], libraryname
);
10084 if (tcc_add_file_internal(s
, buf
, 0) == 0)
10090 int tcc_add_symbol(TCCState
*s
, const char *name
, unsigned long val
)
10092 add_elf_sym(symtab_section
, val
, 0,
10093 ELF32_ST_INFO(STB_GLOBAL
, STT_NOTYPE
), 0,
10098 int tcc_set_output_type(TCCState
*s
, int output_type
)
10100 s
->output_type
= output_type
;
10102 if (!s
->nostdinc
) {
10105 /* default include paths */
10106 /* XXX: reverse order needed if -isystem support */
10107 #ifndef TCC_TARGET_PE
10108 tcc_add_sysinclude_path(s
, "/usr/local/include");
10109 tcc_add_sysinclude_path(s
, "/usr/include");
10111 snprintf(buf
, sizeof(buf
), "%s/include", tcc_lib_path
);
10112 tcc_add_sysinclude_path(s
, buf
);
10113 #ifdef TCC_TARGET_PE
10114 snprintf(buf
, sizeof(buf
), "%s/include/winapi", tcc_lib_path
);
10115 tcc_add_sysinclude_path(s
, buf
);
10119 /* if bound checking, then add corresponding sections */
10120 #ifdef CONFIG_TCC_BCHECK
10121 if (do_bounds_check
) {
10122 /* define symbol */
10123 tcc_define_symbol(s
, "__BOUNDS_CHECKING_ON", NULL
);
10124 /* create bounds sections */
10125 bounds_section
= new_section(s
, ".bounds",
10126 SHT_PROGBITS
, SHF_ALLOC
);
10127 lbounds_section
= new_section(s
, ".lbounds",
10128 SHT_PROGBITS
, SHF_ALLOC
);
10132 if (s
->char_is_unsigned
) {
10133 tcc_define_symbol(s
, "__CHAR_UNSIGNED__", NULL
);
10136 /* add debug sections */
10139 stab_section
= new_section(s
, ".stab", SHT_PROGBITS
, 0);
10140 stab_section
->sh_entsize
= sizeof(Stab_Sym
);
10141 stabstr_section
= new_section(s
, ".stabstr", SHT_STRTAB
, 0);
10142 put_elf_str(stabstr_section
, "");
10143 stab_section
->link
= stabstr_section
;
10144 /* put first entry */
10145 put_stabs("", 0, 0, 0, 0);
10148 /* add libc crt1/crti objects */
10149 #ifndef TCC_TARGET_PE
10150 if ((output_type
== TCC_OUTPUT_EXE
|| output_type
== TCC_OUTPUT_DLL
) &&
10152 if (output_type
!= TCC_OUTPUT_DLL
)
10153 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crt1.o");
10154 tcc_add_file(s
, CONFIG_TCC_CRT_PREFIX
"/crti.o");
10160 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10161 #define FD_INVERT 0x0002 /* invert value before storing */
10163 typedef struct FlagDef
{
10169 static const FlagDef warning_defs
[] = {
10170 { offsetof(TCCState
, warn_unsupported
), 0, "unsupported" },
10171 { offsetof(TCCState
, warn_write_strings
), 0, "write-strings" },
10172 { offsetof(TCCState
, warn_error
), 0, "error" },
10173 { offsetof(TCCState
, warn_implicit_function_declaration
), WD_ALL
,
10174 "implicit-function-declaration" },
10177 static int set_flag(TCCState
*s
, const FlagDef
*flags
, int nb_flags
,
10178 const char *name
, int value
)
10185 if (r
[0] == 'n' && r
[1] == 'o' && r
[2] == '-') {
10189 for(i
= 0, p
= flags
; i
< nb_flags
; i
++, p
++) {
10190 if (!strcmp(r
, p
->name
))
10195 if (p
->flags
& FD_INVERT
)
10197 *(int *)((uint8_t *)s
+ p
->offset
) = value
;
10202 /* set/reset a warning */
10203 int tcc_set_warning(TCCState
*s
, const char *warning_name
, int value
)
10208 if (!strcmp(warning_name
, "all")) {
10209 for(i
= 0, p
= warning_defs
; i
< countof(warning_defs
); i
++, p
++) {
10210 if (p
->flags
& WD_ALL
)
10211 *(int *)((uint8_t *)s
+ p
->offset
) = 1;
10215 return set_flag(s
, warning_defs
, countof(warning_defs
),
10216 warning_name
, value
);
10220 static const FlagDef flag_defs
[] = {
10221 { offsetof(TCCState
, char_is_unsigned
), 0, "unsigned-char" },
10222 { offsetof(TCCState
, char_is_unsigned
), FD_INVERT
, "signed-char" },
10223 { offsetof(TCCState
, nocommon
), FD_INVERT
, "common" },
10224 { offsetof(TCCState
, leading_underscore
), 0, "leading-underscore" },
10227 /* set/reset a flag */
10228 int tcc_set_flag(TCCState
*s
, const char *flag_name
, int value
)
10230 return set_flag(s
, flag_defs
, countof(flag_defs
),
10234 #if !defined(LIBTCC)
10236 /* extract the basename of a file */
10237 static const char *tcc_basename(const char *name
)
10240 p
= strrchr(name
, '/');
10243 p
= strrchr(name
, '\\');
10252 static int64_t getclock_us(void)
10257 return (tb
.time
* 1000LL + tb
.millitm
) * 1000LL;
10260 gettimeofday(&tv
, NULL
);
10261 return tv
.tv_sec
* 1000000LL + tv
.tv_usec
;
10267 printf("tcc version " TCC_VERSION
" - Tiny C Compiler - Copyright (C) 2001-2005 Fabrice Bellard\n"
10268 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10269 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-static]\n"
10270 " [infile1 infile2...] [-run infile args...]\n"
10272 "General options:\n"
10273 " -v display current version\n"
10274 " -c compile only - generate an object file\n"
10275 " -o outfile set output filename\n"
10276 " -Bdir set tcc internal library path\n"
10277 " -bench output compilation statistics\n"
10278 " -run run compiled source\n"
10279 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10280 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10281 " -w disable all warnings\n"
10282 "Preprocessor options:\n"
10283 " -Idir add include path 'dir'\n"
10284 " -Dsym[=val] define 'sym' with value 'val'\n"
10285 " -Usym undefine 'sym'\n"
10286 "Linker options:\n"
10287 " -Ldir add library path 'dir'\n"
10288 " -llib link with dynamic or static library 'lib'\n"
10289 " -shared generate a shared library\n"
10290 " -static static linking\n"
10291 " -rdynamic export all global symbols to dynamic linker\n"
10292 " -r relocatable output\n"
10293 "Debugger options:\n"
10294 " -g generate runtime debug info\n"
10295 #ifdef CONFIG_TCC_BCHECK
10296 " -b compile with built-in memory and bounds checker (implies -g)\n"
10298 " -bt N show N callers in stack traces\n"
10302 #define TCC_OPTION_HAS_ARG 0x0001
10303 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10305 typedef struct TCCOption
{
10333 TCC_OPTION_nostdinc
,
10334 TCC_OPTION_nostdlib
,
10335 TCC_OPTION_print_search_dirs
,
10336 TCC_OPTION_rdynamic
,
10343 static const TCCOption tcc_options
[] = {
10344 { "h", TCC_OPTION_HELP
, 0 },
10345 { "?", TCC_OPTION_HELP
, 0 },
10346 { "I", TCC_OPTION_I
, TCC_OPTION_HAS_ARG
},
10347 { "D", TCC_OPTION_D
, TCC_OPTION_HAS_ARG
},
10348 { "U", TCC_OPTION_U
, TCC_OPTION_HAS_ARG
},
10349 { "L", TCC_OPTION_L
, TCC_OPTION_HAS_ARG
},
10350 { "B", TCC_OPTION_B
, TCC_OPTION_HAS_ARG
},
10351 { "l", TCC_OPTION_l
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10352 { "bench", TCC_OPTION_bench
, 0 },
10353 { "bt", TCC_OPTION_bt
, TCC_OPTION_HAS_ARG
},
10354 #ifdef CONFIG_TCC_BCHECK
10355 { "b", TCC_OPTION_b
, 0 },
10357 { "g", TCC_OPTION_g
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10358 { "c", TCC_OPTION_c
, 0 },
10359 { "static", TCC_OPTION_static
, 0 },
10360 { "shared", TCC_OPTION_shared
, 0 },
10361 { "o", TCC_OPTION_o
, TCC_OPTION_HAS_ARG
},
10362 { "run", TCC_OPTION_run
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10363 { "rdynamic", TCC_OPTION_rdynamic
, 0 },
10364 { "r", TCC_OPTION_r
, 0 },
10365 { "Wl,", TCC_OPTION_Wl
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10366 { "W", TCC_OPTION_W
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10367 { "O", TCC_OPTION_O
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10368 { "m", TCC_OPTION_m
, TCC_OPTION_HAS_ARG
},
10369 { "f", TCC_OPTION_f
, TCC_OPTION_HAS_ARG
| TCC_OPTION_NOSEP
},
10370 { "nostdinc", TCC_OPTION_nostdinc
, 0 },
10371 { "nostdlib", TCC_OPTION_nostdlib
, 0 },
10372 { "print-search-dirs", TCC_OPTION_print_search_dirs
, 0 },
10373 { "v", TCC_OPTION_v
, 0 },
10374 { "w", TCC_OPTION_w
, 0 },
10375 { "pipe", TCC_OPTION_pipe
, 0},
10379 /* convert 'str' into an array of space separated strings */
10380 static int expand_args(char ***pargv
, const char *str
)
10389 while (is_space(*str
))
10394 while (*str
!= '\0' && !is_space(*str
))
10397 arg
= tcc_malloc(len
+ 1);
10398 memcpy(arg
, s1
, len
);
10400 dynarray_add((void ***)&argv
, &argc
, arg
);
10406 static char **files
;
10407 static int nb_files
, nb_libraries
;
10408 static int multiple_files
;
10409 static int print_search_dirs
;
10410 static int output_type
;
10411 static int reloc_output
;
10412 static const char *outfile
;
10414 int parse_args(TCCState
*s
, int argc
, char **argv
)
10417 const TCCOption
*popt
;
10418 const char *optarg
, *p1
, *r1
;
10423 if (optind
>= argc
) {
10424 if (nb_files
== 0 && !print_search_dirs
)
10429 r
= argv
[optind
++];
10431 /* add a new file */
10432 dynarray_add((void ***)&files
, &nb_files
, r
);
10433 if (!multiple_files
) {
10435 /* argv[0] will be this file */
10439 /* find option in table (match only the first chars */
10440 popt
= tcc_options
;
10444 error("invalid option -- '%s'", r
);
10457 if (popt
->flags
& TCC_OPTION_HAS_ARG
) {
10458 if (*r1
!= '\0' || (popt
->flags
& TCC_OPTION_NOSEP
)) {
10461 if (optind
>= argc
)
10462 error("argument to '%s' is missing", r
);
10463 optarg
= argv
[optind
++];
10471 switch(popt
->index
) {
10472 case TCC_OPTION_HELP
:
10477 if (tcc_add_include_path(s
, optarg
) < 0)
10478 error("too many include paths");
10483 sym
= (char *)optarg
;
10484 value
= strchr(sym
, '=');
10489 tcc_define_symbol(s
, sym
, value
);
10493 tcc_undefine_symbol(s
, optarg
);
10496 tcc_add_library_path(s
, optarg
);
10499 /* set tcc utilities path (mainly for tcc development) */
10500 tcc_lib_path
= optarg
;
10503 dynarray_add((void ***)&files
, &nb_files
, r
);
10506 case TCC_OPTION_bench
:
10509 case TCC_OPTION_bt
:
10510 num_callers
= atoi(optarg
);
10512 #ifdef CONFIG_TCC_BCHECK
10514 do_bounds_check
= 1;
10522 multiple_files
= 1;
10523 output_type
= TCC_OUTPUT_OBJ
;
10525 case TCC_OPTION_static
:
10526 s
->static_link
= 1;
10528 case TCC_OPTION_shared
:
10529 output_type
= TCC_OUTPUT_DLL
;
10532 multiple_files
= 1;
10536 /* generate a .o merging several output files */
10538 output_type
= TCC_OUTPUT_OBJ
;
10540 case TCC_OPTION_nostdinc
:
10543 case TCC_OPTION_nostdlib
:
10546 case TCC_OPTION_print_search_dirs
:
10547 print_search_dirs
= 1;
10549 case TCC_OPTION_run
:
10553 argc1
= expand_args(&argv1
, optarg
);
10555 parse_args(s
, argc1
, argv1
);
10557 multiple_files
= 0;
10558 output_type
= TCC_OUTPUT_MEMORY
;
10562 printf("tcc version %s\n", TCC_VERSION
);
10565 if (tcc_set_flag(s
, optarg
, 1) < 0 && s
->warn_unsupported
)
10566 goto unsupported_option
;
10569 if (tcc_set_warning(s
, optarg
, 1) < 0 &&
10570 s
->warn_unsupported
)
10571 goto unsupported_option
;
10576 case TCC_OPTION_rdynamic
:
10579 case TCC_OPTION_Wl
:
10582 if (strstart(optarg
, "-Ttext,", &p
)) {
10583 s
->text_addr
= strtoul(p
, NULL
, 16);
10584 s
->has_text_addr
= 1;
10585 } else if (strstart(optarg
, "--oformat,", &p
)) {
10586 if (strstart(p
, "elf32-", NULL
)) {
10587 s
->output_format
= TCC_OUTPUT_FORMAT_ELF
;
10588 } else if (!strcmp(p
, "binary")) {
10589 s
->output_format
= TCC_OUTPUT_FORMAT_BINARY
;
10591 #ifdef TCC_TARGET_COFF
10592 if (!strcmp(p
, "coff")) {
10593 s
->output_format
= TCC_OUTPUT_FORMAT_COFF
;
10597 error("target %s not found", p
);
10600 error("unsupported linker option '%s'", optarg
);
10605 if (s
->warn_unsupported
) {
10606 unsupported_option
:
10607 warning("unsupported option '%s'", r
);
10616 int main(int argc
, char **argv
)
10620 int nb_objfiles
, ret
, optind
;
10621 char objfilename
[1024];
10622 int64_t start_time
= 0;
10625 /* on win32, we suppose the lib and includes are at the location
10628 static char path
[1024];
10631 GetModuleFileNameA(NULL
, path
, sizeof path
);
10632 p
= d
= strlwr(path
);
10635 if (*d
== '\\') *d
= '/', p
= d
;
10639 tcc_lib_path
= path
;
10644 output_type
= TCC_OUTPUT_EXE
;
10646 multiple_files
= 1;
10651 print_search_dirs
= 0;
10653 optind
= parse_args(s
, argc
- 1, argv
+ 1) + 1;
10655 if (print_search_dirs
) {
10656 /* enough for Linux kernel */
10657 printf("install: %s/\n", tcc_lib_path
);
10661 nb_objfiles
= nb_files
- nb_libraries
;
10663 /* if outfile provided without other options, we output an
10665 if (outfile
&& output_type
== TCC_OUTPUT_MEMORY
)
10666 output_type
= TCC_OUTPUT_EXE
;
10668 /* check -c consistency : only single file handled. XXX: checks file type */
10669 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
10670 /* accepts only a single input file */
10671 if (nb_objfiles
!= 1)
10672 error("cannot specify multiple files with -c");
10673 if (nb_libraries
!= 0)
10674 error("cannot specify libraries with -c");
10677 if (output_type
!= TCC_OUTPUT_MEMORY
) {
10679 /* compute default outfile name */
10680 pstrcpy(objfilename
, sizeof(objfilename
) - 1,
10682 tcc_basename(files
[0]));
10683 #ifdef TCC_TARGET_PE
10684 pe_guess_outfile(objfilename
, output_type
);
10686 if (output_type
== TCC_OUTPUT_OBJ
&& !reloc_output
) {
10687 char *ext
= strrchr(objfilename
, '.');
10689 goto default_outfile
;
10690 /* add .o extension */
10691 strcpy(ext
+ 1, "o");
10694 pstrcpy(objfilename
, sizeof(objfilename
), "a.out");
10697 outfile
= objfilename
;
10702 start_time
= getclock_us();
10705 tcc_set_output_type(s
, output_type
);
10707 /* compile or add each files or library */
10708 for(i
= 0;i
< nb_files
; i
++) {
10709 const char *filename
;
10711 filename
= files
[i
];
10712 if (filename
[0] == '-') {
10713 if (tcc_add_library(s
, filename
+ 2) < 0)
10714 error("cannot find %s", filename
);
10716 if (tcc_add_file(s
, filename
) < 0) {
10723 /* free all files */
10728 total_time
= (double)(getclock_us() - start_time
) / 1000000.0;
10729 if (total_time
< 0.001)
10730 total_time
= 0.001;
10731 if (total_bytes
< 1)
10733 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
10734 tok_ident
- TOK_IDENT
, total_lines
, total_bytes
,
10735 total_time
, (int)(total_lines
/ total_time
),
10736 total_bytes
/ total_time
/ 1000000.0);
10739 if (s
->output_type
== TCC_OUTPUT_MEMORY
) {
10740 ret
= tcc_run(s
, argc
- optind
, argv
+ optind
);
10742 #ifdef TCC_TARGET_PE
10743 if (s
->output_type
!= TCC_OUTPUT_OBJ
) {
10744 ret
= tcc_output_pe(s
, outfile
);
10748 tcc_output_file(s
, outfile
);
10752 /* XXX: cannot do it with bound checking because of the malloc hooks */
10753 if (!do_bounds_check
)
10758 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size
, mem_max_size
);