1 /*
2 * TCC - Tiny C Compiler
3 *
4 * Copyright (c) 2001-2004 Fabrice Bellard
5 *
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.
10 *
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.
15 *
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
19 */
20 #define _GNU_SOURCE
21 #include "config.h"
22
23 #ifdef CONFIG_TCCBOOT
24
25 #include "tccboot.h"
26 #define CONFIG_TCC_STATIC
27
28 #else
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <stdarg.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <math.h>
36 #include <unistd.h>
37 #include <signal.h>
38 #include <fcntl.h>
39 #include <setjmp.h>
40 #include <time.h>
41 #ifdef _WIN32
42 #include <sys/timeb.h>
43 #include <windows.h>
44 #endif
45 #ifndef _WIN32
46 #include <sys/time.h>
47 #include <sys/ucontext.h>
48 #include <sys/mman.h>
49 #endif
50
51 #endif /* !CONFIG_TCCBOOT */
52
53 #ifndef PAGESIZE
54 #define PAGESIZE 4096
55 #endif
56
57 #include "elf.h"
58 #include "stab.h"
59
60 #ifndef O_BINARY
61 #define O_BINARY 0
62 #endif
63
64 #include "libtcc.h"
65
66 /* parser debug */
67 //#define PARSE_DEBUG
68 /* preprocessor debug */
69 //#define PP_DEBUG
70 /* include file debug */
71 //#define INC_DEBUG
72
73 //#define MEM_DEBUG
74
75 /* assembler debug */
76 //#define ASM_DEBUG
77
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 */
82
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
87 #endif
88
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 */
92 #endif
93
94 #if defined(_WIN32) && !defined(TCC_TARGET_PE)
95 #define CONFIG_TCC_STATIC
96 #endif
97
98 /* define it to include assembler support */
99 #if !defined(TCC_TARGET_ARM) && !defined(TCC_TARGET_C67)
100 #define CONFIG_TCC_ASM
101 #endif
102
103 /* object format selection */
104 #if defined(TCC_TARGET_C67)
105 #define TCC_TARGET_COFF
106 #endif
107
108 #define FALSE 0
109 #define false 0
110 #define TRUE 1
111 #define true 1
112 typedef int BOOL;
113
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"
117
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
123
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 */
127
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 */
136 int len;
137 char str[1];
138 } TokenSym;
139
140 #ifdef TCC_TARGET_PE
141 typedef unsigned short nwchar_t;
142 #else
143 typedef int nwchar_t;
144 #endif
145
146 typedef struct CString {
147 int size; /* size in bytes */
148 void *data; /* either 'char *' or 'nwchar_t *' */
149 int size_allocated;
150 void *data_allocated; /* if non NULL, data has been malloced */
151 } CString;
152
153 /* type definition */
154 typedef struct CType {
155 int t;
156 struct Sym *ref;
157 } CType;
158
159 /* constant value */
160 typedef union CValue {
161 long double ld;
162 double d;
163 float f;
164 int i;
165 unsigned int ui;
166 unsigned int ul; /* address (should be unsigned long on 64 bit cpu) */
167 long long ll;
168 unsigned long long ull;
169 struct CString *cstr;
170 void *ptr;
171 int tab[1];
172 } CValue;
173
174 /* value on stack */
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) */
182 } SValue;
183
184 /* symbol management */
185 typedef struct Sym {
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 */
193 } Sym;
194
195 /* section definition */
196 /* XXX: use directly ELF structure for parameters ? */
197 /* special flag to indicate that the section should not be linked to
198 the other ones */
199 #define SHF_PRIVATE 0x80000000
200
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 */
221 } Section;
222
223 typedef struct DLLReference {
224 int level;
225 char name[1];
226 } DLLReference;
227
228 /* GNUC attribute definition */
229 typedef struct AttributeDef {
230 int aligned;
231 int packed;
232 Section *section;
233 int func_attr; /* calling convention, exports, ... */
234 } AttributeDef;
235
236 /* -------------------------------------------------- */
237 /* gr: wrappers for casting sym->r for other purposes */
238 typedef struct {
239 unsigned
240 func_call : 8,
241 func_args : 8,
242 func_export : 1;
243 } func_attr_t;
244
245 #define FUNC_CALL(r) (((func_attr_t*)&(r))->func_call)
246 #define FUNC_EXPORT(r) (((func_attr_t*)&(r))->func_export)
247 #define FUNC_ARGS(r) (((func_attr_t*)&(r))->func_args)
248 #define INLINE_DEF(r) (*(int **)&(r))
249 /* -------------------------------------------------- */
250
251 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
252 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
253 #define SYM_FIRST_ANOM 0x10000000 /* first anonymous sym */
254
255 /* stored in 'Sym.c' field */
256 #define FUNC_NEW 1 /* ansi function prototype */
257 #define FUNC_OLD 2 /* old function prototype */
258 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
259
260 /* stored in 'Sym.r' field */
261 #define FUNC_CDECL 0 /* standard c call */
262 #define FUNC_STDCALL 1 /* pascal c call */
263 #define FUNC_FASTCALL1 2 /* first param in %eax */
264 #define FUNC_FASTCALL2 3 /* first parameters in %eax, %edx */
265 #define FUNC_FASTCALL3 4 /* first parameter in %eax, %edx, %ecx */
266 #define FUNC_FASTCALLW 5 /* first parameter in %ecx, %edx */
267
268 /* field 'Sym.t' for macros */
269 #define MACRO_OBJ 0 /* object like macro */
270 #define MACRO_FUNC 1 /* function like macro */
271
272 /* field 'Sym.r' for C labels */
273 #define LABEL_DEFINED 0 /* label is defined */
274 #define LABEL_FORWARD 1 /* label is forward defined */
275 #define LABEL_DECLARED 2 /* label is declared but never used */
276
277 /* type_decl() types */
278 #define TYPE_ABSTRACT 1 /* type without variable */
279 #define TYPE_DIRECT 2 /* type with variable */
280
281 #define IO_BUF_SIZE 8192
282
283 typedef struct BufferedFile {
284 uint8_t *buf_ptr;
285 uint8_t *buf_end;
286 int fd;
287 int line_num; /* current line number - here to simplify code */
288 int ifndef_macro; /* #ifndef macro / #endif search */
289 int ifndef_macro_saved; /* saved ifndef_macro */
290 int *ifdef_stack_ptr; /* ifdef_stack value at the start of the file */
291 char inc_type; /* type of include */
292 char inc_filename[512]; /* filename specified by the user */
293 char filename[1024]; /* current filename - here to simplify code */
294 unsigned char buffer[IO_BUF_SIZE + 1]; /* extra size for CH_EOB char */
295 } BufferedFile;
296
297 #define CH_EOB '\\' /* end of buffer or '\0' char in file */
298 #define CH_EOF (-1) /* end of file */
299
300 /* parsing state (used to save parser state to reparse part of the
301 source several times) */
302 typedef struct ParseState {
303 int *macro_ptr;
304 int line_num;
305 int tok;
306 CValue tokc;
307 } ParseState;
308
309 /* used to record tokens */
310 typedef struct TokenString {
311 int *str;
312 int len;
313 int allocated_len;
314 int last_line_num;
315 } TokenString;
316
317 /* include file cache, used to find files faster and also to eliminate
318 inclusion if the include file is protected by #ifndef ... #endif */
319 typedef struct CachedInclude {
320 int ifndef_macro;
321 int hash_next; /* -1 if none */
322 char type; /* '"' or '>' to give include type */
323 char filename[1]; /* path specified in #include */
324 } CachedInclude;
325
326 #define CACHED_INCLUDES_HASH_SIZE 512
327
328 /* parser */
329 static struct BufferedFile *file;
330 static int ch, tok;
331 static CValue tokc;
332 static CString tokcstr; /* current parsed string, if any */
333 /* additional informations about token */
334 static int tok_flags;
335 #define TOK_FLAG_BOL 0x0001 /* beginning of line before */
336 #define TOK_FLAG_BOF 0x0002 /* beginning of file before */
337 #define TOK_FLAG_ENDIF 0x0004 /* a endif was found matching starting #ifdef */
338 #define TOK_FLAG_EOF 0x0008 /* end of file */
339
340 static int *macro_ptr, *macro_ptr_allocated;
341 static int *unget_saved_macro_ptr;
342 static int unget_saved_buffer[TOK_MAX_SIZE + 1];
343 static int unget_buffer_enabled;
344 static int parse_flags;
345 #define PARSE_FLAG_PREPROCESS 0x0001 /* activate preprocessing */
346 #define PARSE_FLAG_TOK_NUM 0x0002 /* return numbers instead of TOK_PPNUM */
347 #define PARSE_FLAG_LINEFEED 0x0004 /* line feed is returned as a
348 token. line feed is also
349 returned at eof */
350 #define PARSE_FLAG_ASM_COMMENTS 0x0008 /* '#' can be used for line comment */
351
352 static Section *text_section, *data_section, *bss_section; /* predefined sections */
353 static Section *cur_text_section; /* current section where function code is
354 generated */
355 #ifdef CONFIG_TCC_ASM
356 static Section *last_text_section; /* to handle .previous asm directive */
357 #endif
358 /* bound check related sections */
359 static Section *bounds_section; /* contains global data bound description */
360 static Section *lbounds_section; /* contains local data bound description */
361 /* symbol sections */
362 static Section *symtab_section, *strtab_section;
363
364 /* debug sections */
365 static Section *stab_section, *stabstr_section;
366
367 /* loc : local variable index
368 ind : output code index
369 rsym: return symbol
370 anon_sym: anonymous symbol index
371 */
372 static int rsym, anon_sym, ind, loc;
373 /* expression generation modifiers */
374 static int const_wanted; /* true if constant wanted */
375 static int nocode_wanted; /* true if no code generation wanted for an expression */
376 static int global_expr; /* true if compound literals must be allocated
377 globally (used during initializers parsing */
378 static CType func_vt; /* current function return type (used by return
379 instruction) */
380 static int func_vc;
381 static int last_line_num, last_ind, func_ind; /* debug last line number and pc */
382 static int tok_ident;
383 static TokenSym **table_ident;
384 static TokenSym *hash_ident[TOK_HASH_SIZE];
385 static char token_buf[STRING_MAX_SIZE + 1];
386 static char *funcname;
387 static Sym *global_stack, *local_stack;
388 static Sym *define_stack;
389 static Sym *global_label_stack, *local_label_stack;
390 /* symbol allocator */
391 #define SYM_POOL_NB (8192 / sizeof(Sym))
392 static Sym *sym_free_first;
393
394 static SValue vstack[VSTACK_SIZE], *vtop;
395 /* some predefined types */
396 static CType char_pointer_type, func_old_type, int_type;
397 /* true if isid(c) || isnum(c) */
398 static unsigned char isidnum_table[256];
399
400 /* display some information during compilation */
401 static int verbose = 0;
402
403 /* compile with debug symbol (and use them if error during execution) */
404 static int do_debug = 0;
405
406 /* compile with built-in memory and bounds checker */
407 static int do_bounds_check = 0;
408
409 /* display benchmark infos */
410 #if !defined(LIBTCC)
411 static int do_bench = 0;
412 #endif
413 static int total_lines;
414 static int total_bytes;
415
416 /* use GNU C extensions */
417 static int gnu_ext = 1;
418
419 /* use Tiny C extensions */
420 static int tcc_ext = 1;
421
422 /* max number of callers shown if error */
423 static int num_callers = 6;
424 static const char **rt_bound_error_msg;
425
426 /* XXX: get rid of this ASAP */
427 static struct TCCState *tcc_state;
428
429 /* give the path of the tcc libraries */
430 //static const char *tcc_lib_path = CONFIG_TCCDIR;
431 static char tcc_lib_path[1024];
432
433 struct TCCState {
434 int output_type;
435
436 BufferedFile **include_stack_ptr;
437 int *ifdef_stack_ptr;
438
439 /* include file handling */
440 char **include_paths;
441 int nb_include_paths;
442 char **sysinclude_paths;
443 int nb_sysinclude_paths;
444 CachedInclude **cached_includes;
445 int nb_cached_includes;
446
447 char **library_paths;
448 int nb_library_paths;
449
450 /* array of all loaded dlls (including those referenced by loaded
451 dlls) */
452 DLLReference **loaded_dlls;
453 int nb_loaded_dlls;
454
455 /* sections */
456 Section **sections;
457 int nb_sections; /* number of sections, including first dummy section */
458
459 /* got handling */
460 Section *got;
461 Section *plt;
462 unsigned long *got_offsets;
463 int nb_got_offsets;
464 /* give the correspondance from symtab indexes to dynsym indexes */
465 int *symtab_to_dynsym;
466
467 /* temporary dynamic symbol sections (for dll loading) */
468 Section *dynsymtab_section;
469 /* exported dynamic symbol section */
470 Section *dynsym;
471
472 int nostdinc; /* if true, no standard headers are added */
473 int nostdlib; /* if true, no standard libraries are added */
474
475 int nocommon; /* if true, do not use common symbols for .bss data */
476
477 /* if true, static linking is performed */
478 int static_link;
479
480 /* soname as specified on the command line (-soname) */
481 const char *soname;
482
483 /* if true, all symbols are exported */
484 int rdynamic;
485
486 /* if true, only link in referenced objects from archive */
487 int alacarte_link;
488
489 /* address of text section */
490 unsigned long text_addr;
491 int has_text_addr;
492
493 /* output format, see TCC_OUTPUT_FORMAT_xxx */
494 int output_format;
495
496 /* C language options */
497 int char_is_unsigned;
498 int leading_underscore;
499
500 /* warning switches */
501 int warn_write_strings;
502 int warn_unsupported;
503 int warn_error;
504 int warn_none;
505 int warn_implicit_function_declaration;
506
507 /* error handling */
508 void *error_opaque;
509 void (*error_func)(void *opaque, const char *msg);
510 int error_set_jmp_enabled;
511 jmp_buf error_jmp_buf;
512 int nb_errors;
513
514 /* tiny assembler state */
515 Sym *asm_labels;
516
517 /* see include_stack_ptr */
518 BufferedFile *include_stack[INCLUDE_STACK_SIZE];
519
520 /* see ifdef_stack_ptr */
521 int ifdef_stack[IFDEF_STACK_SIZE];
522
523 /* see cached_includes */
524 int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
525
526 /* pack stack */
527 int pack_stack[PACK_STACK_SIZE];
528 int *pack_stack_ptr;
529
530 /* output file for preprocessing */
531 FILE *outfile;
532 };
533
534 /* The current value can be: */
535 #define VT_VALMASK 0x00ff
536 #define VT_CONST 0x00f0 /* constant in vc
537 (must be first non register value) */
538 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
539 #define VT_LOCAL 0x00f2 /* offset on stack */
540 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
541 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
542 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
543 #define VT_LVAL 0x0100 /* var is an lvalue */
544 #define VT_SYM 0x0200 /* a symbol value is added */
545 #define VT_MUSTCAST 0x0400 /* value must be casted to be correct (used for
546 char/short stored in integer registers) */
547 #define VT_MUSTBOUND 0x0800 /* bound checking must be done before
548 dereferencing value */
549 #define VT_BOUNDED 0x8000 /* value is bounded. The address of the
550 bounding function call point is in vc */
551 #define VT_LVAL_BYTE 0x1000 /* lvalue is a byte */
552 #define VT_LVAL_SHORT 0x2000 /* lvalue is a short */
553 #define VT_LVAL_UNSIGNED 0x4000 /* lvalue is unsigned */
554 #define VT_LVAL_TYPE (VT_LVAL_BYTE | VT_LVAL_SHORT | VT_LVAL_UNSIGNED)
555
556 /* types */
557 #define VT_INT 0 /* integer type */
558 #define VT_BYTE 1 /* signed byte type */
559 #define VT_SHORT 2 /* short type */
560 #define VT_VOID 3 /* void type */
561 #define VT_PTR 4 /* pointer */
562 #define VT_ENUM 5 /* enum definition */
563 #define VT_FUNC 6 /* function type */
564 #define VT_STRUCT 7 /* struct/union definition */
565 #define VT_FLOAT 8 /* IEEE float */
566 #define VT_DOUBLE 9 /* IEEE double */
567 #define VT_LDOUBLE 10 /* IEEE long double */
568 #define VT_BOOL 11 /* ISOC99 boolean type */
569 #define VT_LLONG 12 /* 64 bit integer */
570 #define VT_LONG 13 /* long integer (NEVER USED as type, only
571 during parsing) */
572 #define VT_BTYPE 0x000f /* mask for basic type */
573 #define VT_UNSIGNED 0x0010 /* unsigned type */
574 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
575 #define VT_BITFIELD 0x0040 /* bitfield modifier */
576 #define VT_CONSTANT 0x0800 /* const modifier */
577 #define VT_VOLATILE 0x1000 /* volatile modifier */
578 #define VT_SIGNED 0x2000 /* signed type */
579
580 /* storage */
581 #define VT_EXTERN 0x00000080 /* extern definition */
582 #define VT_STATIC 0x00000100 /* static variable */
583 #define VT_TYPEDEF 0x00000200 /* typedef definition */
584 #define VT_INLINE 0x00000400 /* inline definition */
585
586 #define VT_STRUCT_SHIFT 16 /* shift for bitfield shift values */
587
588 /* type mask (except storage) */
589 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
590 #define VT_TYPE (~(VT_STORAGE))
591
592 /* token values */
593
594 /* warning: the following compare tokens depend on i386 asm code */
595 #define TOK_ULT 0x92
596 #define TOK_UGE 0x93
597 #define TOK_EQ 0x94
598 #define TOK_NE 0x95
599 #define TOK_ULE 0x96
600 #define TOK_UGT 0x97
601 #define TOK_Nset 0x98
602 #define TOK_Nclear 0x99
603 #define TOK_LT 0x9c
604 #define TOK_GE 0x9d
605 #define TOK_LE 0x9e
606 #define TOK_GT 0x9f
607
608 #define TOK_LAND 0xa0
609 #define TOK_LOR 0xa1
610
611 #define TOK_DEC 0xa2
612 #define TOK_MID 0xa3 /* inc/dec, to void constant */
613 #define TOK_INC 0xa4
614 #define TOK_UDIV 0xb0 /* unsigned division */
615 #define TOK_UMOD 0xb1 /* unsigned modulo */
616 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
617 #define TOK_CINT 0xb3 /* number in tokc */
618 #define TOK_CCHAR 0xb4 /* char constant in tokc */
619 #define TOK_STR 0xb5 /* pointer to string in tokc */
620 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
621 #define TOK_LCHAR 0xb7
622 #define TOK_LSTR 0xb8
623 #define TOK_CFLOAT 0xb9 /* float constant */
624 #define TOK_LINENUM 0xba /* line number info */
625 #define TOK_CDOUBLE 0xc0 /* double constant */
626 #define TOK_CLDOUBLE 0xc1 /* long double constant */
627 #define TOK_UMULL 0xc2 /* unsigned 32x32 -> 64 mul */
628 #define TOK_ADDC1 0xc3 /* add with carry generation */
629 #define TOK_ADDC2 0xc4 /* add with carry use */
630 #define TOK_SUBC1 0xc5 /* add with carry generation */
631 #define TOK_SUBC2 0xc6 /* add with carry use */
632 #define TOK_CUINT 0xc8 /* unsigned int constant */
633 #define TOK_CLLONG 0xc9 /* long long constant */
634 #define TOK_CULLONG 0xca /* unsigned long long constant */
635 #define TOK_ARROW 0xcb
636 #define TOK_DOTS 0xcc /* three dots */
637 #define TOK_SHR 0xcd /* unsigned shift right */
638 #define TOK_PPNUM 0xce /* preprocessor number */
639
640 #define TOK_SHL 0x01 /* shift left */
641 #define TOK_SAR 0x02 /* signed shift right */
642
643 /* assignement operators : normal operator or 0x80 */
644 #define TOK_A_MOD 0xa5
645 #define TOK_A_AND 0xa6
646 #define TOK_A_MUL 0xaa
647 #define TOK_A_ADD 0xab
648 #define TOK_A_SUB 0xad
649 #define TOK_A_DIV 0xaf
650 #define TOK_A_XOR 0xde
651 #define TOK_A_OR 0xfc
652 #define TOK_A_SHL 0x81
653 #define TOK_A_SAR 0x82
654
655 #ifndef offsetof
656 #define offsetof(type, field) ((size_t) &((type *)0)->field)
657 #endif
658
659 #ifndef countof
660 #define countof(tab) (sizeof(tab) / sizeof((tab)[0]))
661 #endif
662
663 /* WARNING: the content of this string encodes token numbers */
664 static char tok_two_chars[] = "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\313..\250##\266";
665
666 #define TOK_EOF (-1) /* end of file */
667 #define TOK_LINEFEED 10 /* line feed */
668
669 /* all identificators and strings have token above that */
670 #define TOK_IDENT 256
671
672 /* only used for i386 asm opcodes definitions */
673 #define DEF_ASM(x) DEF(TOK_ASM_ ## x, #x)
674
675 #define DEF_BWL(x) \
676 DEF(TOK_ASM_ ## x ## b, #x "b") \
677 DEF(TOK_ASM_ ## x ## w, #x "w") \
678 DEF(TOK_ASM_ ## x ## l, #x "l") \
679 DEF(TOK_ASM_ ## x, #x)
680
681 #define DEF_WL(x) \
682 DEF(TOK_ASM_ ## x ## w, #x "w") \
683 DEF(TOK_ASM_ ## x ## l, #x "l") \
684 DEF(TOK_ASM_ ## x, #x)
685
686 #define DEF_FP1(x) \
687 DEF(TOK_ASM_ ## f ## x ## s, "f" #x "s") \
688 DEF(TOK_ASM_ ## fi ## x ## l, "fi" #x "l") \
689 DEF(TOK_ASM_ ## f ## x ## l, "f" #x "l") \
690 DEF(TOK_ASM_ ## fi ## x ## s, "fi" #x "s")
691
692 #define DEF_FP(x) \
693 DEF(TOK_ASM_ ## f ## x, "f" #x ) \
694 DEF(TOK_ASM_ ## f ## x ## p, "f" #x "p") \
695 DEF_FP1(x)
696
697 #define DEF_ASMTEST(x) \
698 DEF_ASM(x ## o) \
699 DEF_ASM(x ## no) \
700 DEF_ASM(x ## b) \
701 DEF_ASM(x ## c) \
702 DEF_ASM(x ## nae) \
703 DEF_ASM(x ## nb) \
704 DEF_ASM(x ## nc) \
705 DEF_ASM(x ## ae) \
706 DEF_ASM(x ## e) \
707 DEF_ASM(x ## z) \
708 DEF_ASM(x ## ne) \
709 DEF_ASM(x ## nz) \
710 DEF_ASM(x ## be) \
711 DEF_ASM(x ## na) \
712 DEF_ASM(x ## nbe) \
713 DEF_ASM(x ## a) \
714 DEF_ASM(x ## s) \
715 DEF_ASM(x ## ns) \
716 DEF_ASM(x ## p) \
717 DEF_ASM(x ## pe) \
718 DEF_ASM(x ## np) \
719 DEF_ASM(x ## po) \
720 DEF_ASM(x ## l) \
721 DEF_ASM(x ## nge) \
722 DEF_ASM(x ## nl) \
723 DEF_ASM(x ## ge) \
724 DEF_ASM(x ## le) \
725 DEF_ASM(x ## ng) \
726 DEF_ASM(x ## nle) \
727 DEF_ASM(x ## g)
728
729 #define TOK_ASM_int TOK_INT
730
731 enum tcc_token {
732 TOK_LAST = TOK_IDENT - 1,
733 #define DEF(id, str) id,
734 #include "tcctok.h"
735 #undef DEF
736 };
737
738 static const char tcc_keywords[] =
739 #define DEF(id, str) str "\0"
740 #include "tcctok.h"
741 #undef DEF
742 ;
743
744 #define TOK_UIDENT TOK_DEFINE
745
746 #ifdef _WIN32
747 #define snprintf _snprintf
748 #define vsnprintf _vsnprintf
749 #ifndef __GNUC__
750 #define strtold (long double)strtod
751 #define strtof (float)strtod
752 #define strtoll (long long)strtol
753 #endif
754 #elif defined(TCC_UCLIBC) || defined(__FreeBSD__) || defined(__DragonFly__) \
755 || defined(__OpenBSD__)
756 /* currently incorrect */
strtold(const char * nptr,char ** endptr)757 long double strtold(const char *nptr, char **endptr)
758 {
759 return (long double)strtod(nptr, endptr);
760 }
strtof(const char * nptr,char ** endptr)761 float strtof(const char *nptr, char **endptr)
762 {
763 return (float)strtod(nptr, endptr);
764 }
765 #else
766 /* XXX: need to define this to use them in non ISOC99 context */
767 extern float strtof (const char *__nptr, char **__endptr);
768 extern long double strtold (const char *__nptr, char **__endptr);
769 #endif
770
771 static char *pstrcpy(char *buf, int buf_size, const char *s);
772 static char *pstrcat(char *buf, int buf_size, const char *s);
773 static char *tcc_basename(const char *name);
774 static char *tcc_fileextension (const char *p);
775
776 static void next(void);
777 static void next_nomacro(void);
778 static void parse_expr_type(CType *type);
779 static void expr_type(CType *type);
780 static void unary_type(CType *type);
781 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
782 int case_reg, int is_expr);
783 static int expr_const(void);
784 static void expr_eq(void);
785 static void gexpr(void);
786 static void gen_inline_functions(void);
787 static void decl(int l);
788 static void decl_initializer(CType *type, Section *sec, unsigned long c,
789 int first, int size_only);
790 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
791 int has_init, int v, int scope);
792 int gv(int rc);
793 void gv2(int rc1, int rc2);
794 void move_reg(int r, int s);
795 void save_regs(int n);
796 void save_reg(int r);
797 void vpop(void);
798 void vswap(void);
799 void vdup(void);
800 int get_reg(int rc);
801 int get_reg_ex(int rc,int rc2);
802
803 struct macro_level {
804 struct macro_level *prev;
805 int *p;
806 };
807
808 static void macro_subst(TokenString *tok_str, Sym **nested_list,
809 const int *macro_str, struct macro_level **can_read_stream);
810 void gen_op(int op);
811 void force_charshort_cast(int t);
812 static void gen_cast(CType *type);
813 void vstore(void);
814 static Sym *sym_find(int v);
815 static Sym *sym_push(int v, CType *type, int r, int c);
816
817 /* type handling */
818 static int type_size(CType *type, int *a);
819 static inline CType *pointed_type(CType *type);
820 static int pointed_size(CType *type);
821 static int lvalue_type(int t);
822 static int parse_btype(CType *type, AttributeDef *ad);
823 static void type_decl(CType *type, AttributeDef *ad, int *v, int td);
824 static int compare_types(CType *type1, CType *type2, int unqualified);
825 static int is_compatible_types(CType *type1, CType *type2);
826 static int is_compatible_parameter_types(CType *type1, CType *type2);
827
828 int ieee_finite(double d);
829 void error(const char *fmt, ...);
830 void vpushi(int v);
831 void vrott(int n);
832 void vnrott(int n);
833 void lexpand_nr(void);
834 static void vpush_global_sym(CType *type, int v);
835 void vset(CType *type, int r, int v);
836 void type_to_str(char *buf, int buf_size,
837 CType *type, const char *varstr);
838 char *get_tok_str(int v, CValue *cv);
839 static Sym *get_sym_ref(CType *type, Section *sec,
840 unsigned long offset, unsigned long size);
841 static Sym *external_global_sym(int v, CType *type, int r);
842
843 /* section generation */
844 static void section_realloc(Section *sec, unsigned long new_size);
845 static void *section_ptr_add(Section *sec, unsigned long size);
846 static void put_extern_sym(Sym *sym, Section *section,
847 unsigned long value, unsigned long size);
848 static void greloc(Section *s, Sym *sym, unsigned long addr, int type);
849 static int put_elf_str(Section *s, const char *sym);
850 static int put_elf_sym(Section *s,
851 unsigned long value, unsigned long size,
852 int info, int other, int shndx, const char *name);
853 static int add_elf_sym(Section *s, unsigned long value, unsigned long size,
854 int info, int other, int sh_num, const char *name);
855 static void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
856 int type, int symbol);
857 static void put_stabs(const char *str, int type, int other, int desc,
858 unsigned long value);
859 static void put_stabs_r(const char *str, int type, int other, int desc,
860 unsigned long value, Section *sec, int sym_index);
861 static void put_stabn(int type, int other, int desc, int value);
862 static void put_stabd(int type, int other, int desc);
863 static int tcc_add_dll(TCCState *s, const char *filename, int flags);
864
865 #define AFF_PRINT_ERROR 0x0001 /* print error if file not found */
866 #define AFF_REFERENCED_DLL 0x0002 /* load a referenced dll from another dll */
867 #define AFF_PREPROCESS 0x0004 /* preprocess file */
868 static int tcc_add_file_internal(TCCState *s, const char *filename, int flags);
869
870 /* tcccoff.c */
871 int tcc_output_coff(TCCState *s1, FILE *f);
872
873 /* tccpe.c */
874 void *resolve_sym(TCCState *s1, const char *sym, int type);
875 int pe_load_def_file(struct TCCState *s1, int fd);
876 int pe_test_res_file(void *v, int size);
877 int pe_load_res_file(struct TCCState *s1, int fd);
878 void pe_add_runtime(struct TCCState *s1);
879 void pe_guess_outfile(char *objfilename, int output_type);
880 int pe_output_file(struct TCCState *s1, const char *filename);
881
882 /* tccasm.c */
883
884 #ifdef CONFIG_TCC_ASM
885
886 typedef struct ExprValue {
887 uint32_t v;
888 Sym *sym;
889 } ExprValue;
890
891 #define MAX_ASM_OPERANDS 30
892
893 typedef struct ASMOperand {
894 int id; /* GCC 3 optionnal identifier (0 if number only supported */
895 char *constraint;
896 char asm_str[16]; /* computed asm string for operand */
897 SValue *vt; /* C value of the expression */
898 int ref_index; /* if >= 0, gives reference to a output constraint */
899 int input_index; /* if >= 0, gives reference to an input constraint */
900 int priority; /* priority, used to assign registers */
901 int reg; /* if >= 0, register number used for this operand */
902 int is_llong; /* true if double register value */
903 int is_memory; /* true if memory operand */
904 int is_rw; /* for '+' modifier */
905 } ASMOperand;
906
907 static void asm_expr(TCCState *s1, ExprValue *pe);
908 static int asm_int_expr(TCCState *s1);
909 static int find_constraint(ASMOperand *operands, int nb_operands,
910 const char *name, const char **pp);
911
912 static int tcc_assemble(TCCState *s1, int do_preprocess);
913
914 #endif
915
916 static void asm_instr(void);
917 static void asm_global_instr(void);
918
919 /* true if float/double/long double type */
is_float(int t)920 static inline int is_float(int t)
921 {
922 int bt;
923 bt = t & VT_BTYPE;
924 return bt == VT_LDOUBLE || bt == VT_DOUBLE || bt == VT_FLOAT;
925 }
926
927 #ifdef TCC_TARGET_I386
928 #include "i386-gen.c"
929 #endif
930
931 #ifdef TCC_TARGET_ARM
932 #include "arm-gen.c"
933 #endif
934
935 #ifdef TCC_TARGET_C67
936 #include "c67-gen.c"
937 #endif
938
939 #ifdef CONFIG_TCC_STATIC
940
941 #define RTLD_LAZY 0x001
942 #define RTLD_NOW 0x002
943 #define RTLD_GLOBAL 0x100
944 #define RTLD_DEFAULT NULL
945
946 /* dummy function for profiling */
dlopen(const char * filename,int flag)947 void *dlopen(const char *filename, int flag)
948 {
949 return NULL;
950 }
951
dlerror(void)952 const char *dlerror(void)
953 {
954 return "error";
955 }
956
957 typedef struct TCCSyms {
958 char *str;
959 void *ptr;
960 } TCCSyms;
961
962 #define TCCSYM(a) { #a, &a, },
963
964 /* add the symbol you want here if no dynamic linking is done */
965 static TCCSyms tcc_syms[] = {
966 #if !defined(CONFIG_TCCBOOT)
967 TCCSYM(printf)
968 TCCSYM(fprintf)
969 TCCSYM(fopen)
970 TCCSYM(fclose)
971 #endif
972 { NULL, NULL },
973 };
974
resolve_sym(TCCState * s1,const char * symbol,int type)975 void *resolve_sym(TCCState *s1, const char *symbol, int type)
976 {
977 TCCSyms *p;
978 p = tcc_syms;
979 while (p->str != NULL) {
980 if (!strcmp(p->str, symbol))
981 return p->ptr;
982 p++;
983 }
984 return NULL;
985 }
986
987 #elif !defined(_WIN32)
988
989 #include <dlfcn.h>
990
resolve_sym(TCCState * s1,const char * sym,int type)991 void *resolve_sym(TCCState *s1, const char *sym, int type)
992 {
993 return dlsym(RTLD_DEFAULT, sym);
994 }
995
996 #endif
997
998 /********************************************************/
999
1000 /* we use our own 'finite' function to avoid potential problems with
1001 non standard math libs */
1002 /* XXX: endianness dependent */
ieee_finite(double d)1003 int ieee_finite(double d)
1004 {
1005 int *p = (int *)&d;
1006 return ((unsigned)((p[1] | 0x800fffff) + 1)) >> 31;
1007 }
1008
1009 /* copy a string and truncate it. */
pstrcpy(char * buf,int buf_size,const char * s)1010 static char *pstrcpy(char *buf, int buf_size, const char *s)
1011 {
1012 char *q, *q_end;
1013 int c;
1014
1015 if (buf_size > 0) {
1016 q = buf;
1017 q_end = buf + buf_size - 1;
1018 while (q < q_end) {
1019 c = *s++;
1020 if (c == '\0')
1021 break;
1022 *q++ = c;
1023 }
1024 *q = '\0';
1025 }
1026 return buf;
1027 }
1028
1029 /* strcat and truncate. */
pstrcat(char * buf,int buf_size,const char * s)1030 static char *pstrcat(char *buf, int buf_size, const char *s)
1031 {
1032 int len;
1033 len = strlen(buf);
1034 if (len < buf_size)
1035 pstrcpy(buf + len, buf_size - len, s);
1036 return buf;
1037 }
1038
1039 #ifndef LIBTCC
strstart(const char * str,const char * val,const char ** ptr)1040 static int strstart(const char *str, const char *val, const char **ptr)
1041 {
1042 const char *p, *q;
1043 p = str;
1044 q = val;
1045 while (*q != '\0') {
1046 if (*p != *q)
1047 return 0;
1048 p++;
1049 q++;
1050 }
1051 if (ptr)
1052 *ptr = p;
1053 return 1;
1054 }
1055 #endif
1056
1057 /* extract the basename of a file */
tcc_basename(const char * name)1058 static char *tcc_basename(const char *name)
1059 {
1060 char *p = strchr(name, 0);
1061 while (p > name
1062 && p[-1] != '/'
1063 #ifdef _WIN32
1064 && p[-1] != '\\'
1065 #endif
1066 )
1067 --p;
1068 return p;
1069 }
1070
tcc_fileextension(const char * name)1071 static char *tcc_fileextension (const char *name)
1072 {
1073 char *b = tcc_basename(name);
1074 char *e = strrchr(b, '.');
1075 return e ? e : strchr(b, 0);
1076 }
1077
1078 #ifdef _WIN32
normalize_slashes(char * path)1079 char *normalize_slashes(char *path)
1080 {
1081 char *p;
1082 for (p = path; *p; ++p)
1083 if (*p == '\\')
1084 *p = '/';
1085 return path;
1086 }
1087
w32_tcc_lib_path(void)1088 char *w32_tcc_lib_path(void)
1089 {
1090 /* on win32, we suppose the lib and includes are at the location
1091 of 'tcc.exe' */
1092 char path[1024], *p;
1093 GetModuleFileNameA(NULL, path, sizeof path);
1094 p = tcc_basename(normalize_slashes(strlwr(path)));
1095 if (p - 5 > path && 0 == strncmp(p - 5, "/bin/", 5))
1096 p -= 5;
1097 else if (p > path)
1098 p--;
1099 *p = 0;
1100 return strdup(path);
1101 }
1102 #endif
1103
set_pages_executable(void * ptr,unsigned long length)1104 void set_pages_executable(void *ptr, unsigned long length)
1105 {
1106 #ifdef _WIN32
1107 unsigned long old_protect;
1108 VirtualProtect(ptr, length, PAGE_EXECUTE_READWRITE, &old_protect);
1109 #else
1110 unsigned long start, end;
1111 start = (unsigned long)ptr & ~(PAGESIZE - 1);
1112 end = (unsigned long)ptr + length;
1113 end = (end + PAGESIZE - 1) & ~(PAGESIZE - 1);
1114 mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC);
1115 #endif
1116 }
1117
1118 /* memory management */
1119 #ifdef MEM_DEBUG
1120 int mem_cur_size;
1121 int mem_max_size;
1122 #endif
1123
tcc_free(void * ptr)1124 static inline void tcc_free(void *ptr)
1125 {
1126 #ifdef MEM_DEBUG
1127 mem_cur_size -= malloc_usable_size(ptr);
1128 #endif
1129 free(ptr);
1130 }
1131
tcc_malloc(unsigned long size)1132 static void *tcc_malloc(unsigned long size)
1133 {
1134 void *ptr;
1135 ptr = malloc(size);
1136 if (!ptr && size)
1137 error("memory full");
1138 #ifdef MEM_DEBUG
1139 mem_cur_size += malloc_usable_size(ptr);
1140 if (mem_cur_size > mem_max_size)
1141 mem_max_size = mem_cur_size;
1142 #endif
1143 return ptr;
1144 }
1145
tcc_mallocz(unsigned long size)1146 static void *tcc_mallocz(unsigned long size)
1147 {
1148 void *ptr;
1149 ptr = tcc_malloc(size);
1150 memset(ptr, 0, size);
1151 return ptr;
1152 }
1153
tcc_realloc(void * ptr,unsigned long size)1154 static inline void *tcc_realloc(void *ptr, unsigned long size)
1155 {
1156 void *ptr1;
1157 #ifdef MEM_DEBUG
1158 mem_cur_size -= malloc_usable_size(ptr);
1159 #endif
1160 ptr1 = realloc(ptr, size);
1161 #ifdef MEM_DEBUG
1162 /* NOTE: count not correct if alloc error, but not critical */
1163 mem_cur_size += malloc_usable_size(ptr1);
1164 if (mem_cur_size > mem_max_size)
1165 mem_max_size = mem_cur_size;
1166 #endif
1167 return ptr1;
1168 }
1169
tcc_strdup(const char * str)1170 static char *tcc_strdup(const char *str)
1171 {
1172 char *ptr;
1173 ptr = tcc_malloc(strlen(str) + 1);
1174 strcpy(ptr, str);
1175 return ptr;
1176 }
1177
1178 #define free(p) use_tcc_free(p)
1179 #define malloc(s) use_tcc_malloc(s)
1180 #define realloc(p, s) use_tcc_realloc(p, s)
1181
dynarray_add(void *** ptab,int * nb_ptr,void * data)1182 static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
1183 {
1184 int nb, nb_alloc;
1185 void **pp;
1186
1187 nb = *nb_ptr;
1188 pp = *ptab;
1189 /* every power of two we double array size */
1190 if ((nb & (nb - 1)) == 0) {
1191 if (!nb)
1192 nb_alloc = 1;
1193 else
1194 nb_alloc = nb * 2;
1195 pp = tcc_realloc(pp, nb_alloc * sizeof(void *));
1196 if (!pp)
1197 error("memory full");
1198 *ptab = pp;
1199 }
1200 pp[nb++] = data;
1201 *nb_ptr = nb;
1202 }
1203
dynarray_reset(void * pp,int * n)1204 static void dynarray_reset(void *pp, int *n)
1205 {
1206 void **p;
1207 for (p = *(void***)pp; *n; ++p, --*n)
1208 if (*p)
1209 tcc_free(*p);
1210 tcc_free(*(void**)pp);
1211 *(void**)pp = NULL;
1212 }
1213
1214 /* symbol allocator */
__sym_malloc(void)1215 static Sym *__sym_malloc(void)
1216 {
1217 Sym *sym_pool, *sym, *last_sym;
1218 int i;
1219
1220 sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
1221
1222 last_sym = sym_free_first;
1223 sym = sym_pool;
1224 for(i = 0; i < SYM_POOL_NB; i++) {
1225 sym->next = last_sym;
1226 last_sym = sym;
1227 sym++;
1228 }
1229 sym_free_first = last_sym;
1230 return last_sym;
1231 }
1232
sym_malloc(void)1233 static inline Sym *sym_malloc(void)
1234 {
1235 Sym *sym;
1236 sym = sym_free_first;
1237 if (!sym)
1238 sym = __sym_malloc();
1239 sym_free_first = sym->next;
1240 return sym;
1241 }
1242
sym_free(Sym * sym)1243 static inline void sym_free(Sym *sym)
1244 {
1245 sym->next = sym_free_first;
1246 sym_free_first = sym;
1247 }
1248
new_section(TCCState * s1,const char * name,int sh_type,int sh_flags)1249 Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
1250 {
1251 Section *sec;
1252
1253 sec = tcc_mallocz(sizeof(Section) + strlen(name));
1254 strcpy(sec->name, name);
1255 sec->sh_type = sh_type;
1256 sec->sh_flags = sh_flags;
1257 switch(sh_type) {
1258 case SHT_HASH:
1259 case SHT_REL:
1260 case SHT_DYNSYM:
1261 case SHT_SYMTAB:
1262 case SHT_DYNAMIC:
1263 sec->sh_addralign = 4;
1264 break;
1265 case SHT_STRTAB:
1266 sec->sh_addralign = 1;
1267 break;
1268 default:
1269 sec->sh_addralign = 32; /* default conservative alignment */
1270 break;
1271 }
1272
1273 /* only add section if not private */
1274 if (!(sh_flags & SHF_PRIVATE)) {
1275 sec->sh_num = s1->nb_sections;
1276 dynarray_add((void ***)&s1->sections, &s1->nb_sections, sec);
1277 }
1278 return sec;
1279 }
1280
free_section(Section * s)1281 static void free_section(Section *s)
1282 {
1283 tcc_free(s->data);
1284 tcc_free(s);
1285 }
1286
1287 /* realloc section and set its content to zero */
section_realloc(Section * sec,unsigned long new_size)1288 static void section_realloc(Section *sec, unsigned long new_size)
1289 {
1290 unsigned long size;
1291 unsigned char *data;
1292
1293 size = sec->data_allocated;
1294 if (size == 0)
1295 size = 1;
1296 while (size < new_size)
1297 size = size * 2;
1298 data = tcc_realloc(sec->data, size);
1299 if (!data)
1300 error("memory full");
1301 memset(data + sec->data_allocated, 0, size - sec->data_allocated);
1302 sec->data = data;
1303 sec->data_allocated = size;
1304 }
1305
1306 /* reserve at least 'size' bytes in section 'sec' from
1307 sec->data_offset. */
section_ptr_add(Section * sec,unsigned long size)1308 static void *section_ptr_add(Section *sec, unsigned long size)
1309 {
1310 unsigned long offset, offset1;
1311
1312 offset = sec->data_offset;
1313 offset1 = offset + size;
1314 if (offset1 > sec->data_allocated)
1315 section_realloc(sec, offset1);
1316 sec->data_offset = offset1;
1317 return sec->data + offset;
1318 }
1319
1320 /* return a reference to a section, and create it if it does not
1321 exists */
find_section(TCCState * s1,const char * name)1322 Section *find_section(TCCState *s1, const char *name)
1323 {
1324 Section *sec;
1325 int i;
1326 for(i = 1; i < s1->nb_sections; i++) {
1327 sec = s1->sections[i];
1328 if (!strcmp(name, sec->name))
1329 return sec;
1330 }
1331 /* sections are created as PROGBITS */
1332 return new_section(s1, name, SHT_PROGBITS, SHF_ALLOC);
1333 }
1334
1335 #define SECTION_ABS ((void *)1)
1336
1337 /* update sym->c so that it points to an external symbol in section
1338 'section' with value 'value' */
put_extern_sym2(Sym * sym,Section * section,unsigned long value,unsigned long size,int can_add_underscore)1339 static void put_extern_sym2(Sym *sym, Section *section,
1340 unsigned long value, unsigned long size,
1341 int can_add_underscore)
1342 {
1343 int sym_type, sym_bind, sh_num, info, other, attr;
1344 Elf32_Sym *esym;
1345 const char *name;
1346 char buf1[256];
1347
1348 if (section == NULL)
1349 sh_num = SHN_UNDEF;
1350 else if (section == SECTION_ABS)
1351 sh_num = SHN_ABS;
1352 else
1353 sh_num = section->sh_num;
1354
1355 other = attr = 0;
1356
1357 if ((sym->type.t & VT_BTYPE) == VT_FUNC) {
1358 sym_type = STT_FUNC;
1359 #ifdef TCC_TARGET_PE
1360 if (sym->type.ref)
1361 attr = sym->type.ref->r;
1362 if (FUNC_EXPORT(attr))
1363 other |= 1;
1364 if (FUNC_CALL(attr) == FUNC_STDCALL)
1365 other |= 2;
1366 #endif
1367 } else {
1368 sym_type = STT_OBJECT;
1369 }
1370
1371 if (sym->type.t & VT_STATIC)
1372 sym_bind = STB_LOCAL;
1373 else
1374 sym_bind = STB_GLOBAL;
1375
1376 if (!sym->c) {
1377 name = get_tok_str(sym->v, NULL);
1378 #ifdef CONFIG_TCC_BCHECK
1379 if (do_bounds_check) {
1380 char buf[32];
1381
1382 /* XXX: avoid doing that for statics ? */
1383 /* if bound checking is activated, we change some function
1384 names by adding the "__bound" prefix */
1385 switch(sym->v) {
1386 #if 0
1387 /* XXX: we rely only on malloc hooks */
1388 case TOK_malloc:
1389 case TOK_free:
1390 case TOK_realloc:
1391 case TOK_memalign:
1392 case TOK_calloc:
1393 #endif
1394 case TOK_memcpy:
1395 case TOK_memmove:
1396 case TOK_memset:
1397 case TOK_strlen:
1398 case TOK_strcpy:
1399 case TOK__alloca:
1400 strcpy(buf, "__bound_");
1401 strcat(buf, name);
1402 name = buf;
1403 break;
1404 }
1405 }
1406 #endif
1407
1408 #ifdef TCC_TARGET_PE
1409 if ((other & 2) && can_add_underscore) {
1410 sprintf(buf1, "_%s@%d", name, FUNC_ARGS(attr));
1411 name = buf1;
1412 } else
1413 #endif
1414 if (tcc_state->leading_underscore && can_add_underscore) {
1415 buf1[0] = '_';
1416 pstrcpy(buf1 + 1, sizeof(buf1) - 1, name);
1417 name = buf1;
1418 }
1419 info = ELF32_ST_INFO(sym_bind, sym_type);
1420 sym->c = add_elf_sym(symtab_section, value, size, info, other, sh_num, name);
1421 } else {
1422 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
1423 esym->st_value = value;
1424 esym->st_size = size;
1425 esym->st_shndx = sh_num;
1426 esym->st_other |= other;
1427 }
1428 }
1429
put_extern_sym(Sym * sym,Section * section,unsigned long value,unsigned long size)1430 static void put_extern_sym(Sym *sym, Section *section,
1431 unsigned long value, unsigned long size)
1432 {
1433 put_extern_sym2(sym, section, value, size, 1);
1434 }
1435
1436 /* add a new relocation entry to symbol 'sym' in section 's' */
greloc(Section * s,Sym * sym,unsigned long offset,int type)1437 static void greloc(Section *s, Sym *sym, unsigned long offset, int type)
1438 {
1439 if (!sym->c)
1440 put_extern_sym(sym, NULL, 0, 0);
1441 /* now we can add ELF relocation info */
1442 put_elf_reloc(symtab_section, s, offset, type, sym->c);
1443 }
1444
isid(int c)1445 static inline int isid(int c)
1446 {
1447 return (c >= 'a' && c <= 'z') ||
1448 (c >= 'A' && c <= 'Z') ||
1449 c == '_';
1450 }
1451
isnum(int c)1452 static inline int isnum(int c)
1453 {
1454 return c >= '0' && c <= '9';
1455 }
1456
isoct(int c)1457 static inline int isoct(int c)
1458 {
1459 return c >= '0' && c <= '7';
1460 }
1461
toup(int c)1462 static inline int toup(int c)
1463 {
1464 if (c >= 'a' && c <= 'z')
1465 return c - 'a' + 'A';
1466 else
1467 return c;
1468 }
1469
strcat_vprintf(char * buf,int buf_size,const char * fmt,va_list ap)1470 static void strcat_vprintf(char *buf, int buf_size, const char *fmt, va_list ap)
1471 {
1472 int len;
1473 len = strlen(buf);
1474 vsnprintf(buf + len, buf_size - len, fmt, ap);
1475 }
1476
strcat_printf(char * buf,int buf_size,const char * fmt,...)1477 static void strcat_printf(char *buf, int buf_size, const char *fmt, ...)
1478 {
1479 va_list ap;
1480 va_start(ap, fmt);
1481 strcat_vprintf(buf, buf_size, fmt, ap);
1482 va_end(ap);
1483 }
1484
error1(TCCState * s1,int is_warning,const char * fmt,va_list ap)1485 void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
1486 {
1487 char buf[2048];
1488 BufferedFile **f;
1489
1490 buf[0] = '\0';
1491 if (file) {
1492 for(f = s1->include_stack; f < s1->include_stack_ptr; f++)
1493 strcat_printf(buf, sizeof(buf), "In file included from %s:%d:\n",
1494 (*f)->filename, (*f)->line_num);
1495 if (file->line_num > 0) {
1496 strcat_printf(buf, sizeof(buf),
1497 "Line %d: ", file->line_num);
1498 } else {
1499 strcat_printf(buf, sizeof(buf),
1500 "%s: ", file->filename);
1501 }
1502 } else {
1503 strcat_printf(buf, sizeof(buf),
1504 "tcc: ");
1505 }
1506 if (is_warning)
1507 strcat_printf(buf, sizeof(buf), "warning: ");
1508 strcat_vprintf(buf, sizeof(buf), fmt, ap);
1509
1510 if (!s1->error_func) {
1511 /* default case: stderr */
1512 fprintf(stderr, "%s\n", buf);
1513 } else {
1514 s1->error_func(s1->error_opaque, buf);
1515 }
1516 if (!is_warning || s1->warn_error)
1517 s1->nb_errors++;
1518 }
1519
1520 #ifdef LIBTCC
tcc_set_error_func(TCCState * s,void * error_opaque,void (* error_func)(void * opaque,const char * msg))1521 void tcc_set_error_func(TCCState *s, void *error_opaque,
1522 void (*error_func)(void *opaque, const char *msg))
1523 {
1524 s->error_opaque = error_opaque;
1525 s->error_func = error_func;
1526 }
1527 #endif
1528
1529 /* error without aborting current compilation */
error_noabort(const char * fmt,...)1530 void error_noabort(const char *fmt, ...)
1531 {
1532 TCCState *s1 = tcc_state;
1533 va_list ap;
1534
1535 va_start(ap, fmt);
1536 error1(s1, 0, fmt, ap);
1537 va_end(ap);
1538 }
1539
error(const char * fmt,...)1540 void error(const char *fmt, ...)
1541 {
1542 TCCState *s1 = tcc_state;
1543 va_list ap;
1544
1545 va_start(ap, fmt);
1546 error1(s1, 0, fmt, ap);
1547 va_end(ap);
1548 /* better than nothing: in some cases, we accept to handle errors */
1549 if (s1->error_set_jmp_enabled) {
1550 longjmp(s1->error_jmp_buf, 1);
1551 } else {
1552 /* XXX: eliminate this someday */
1553 exit(1);
1554 }
1555 }
1556
expect(const char * msg)1557 void expect(const char *msg)
1558 {
1559 error("%s expected", msg);
1560 }
1561
warning(const char * fmt,...)1562 void warning(const char *fmt, ...)
1563 {
1564 TCCState *s1 = tcc_state;
1565 va_list ap;
1566
1567 if (s1->warn_none)
1568 return;
1569
1570 va_start(ap, fmt);
1571 error1(s1, 1, fmt, ap);
1572 va_end(ap);
1573 }
1574
skip(int c)1575 void skip(int c)
1576 {
1577 if (tok != c)
1578 error("'%c' expected", c);
1579 next();
1580 }
1581
test_lvalue(void)1582 static void test_lvalue(void)
1583 {
1584 if (!(vtop->r & VT_LVAL))
1585 expect("lvalue");
1586 }
1587
1588 /* allocate a new token */
tok_alloc_new(TokenSym ** pts,const char * str,int len)1589 static TokenSym *tok_alloc_new(TokenSym **pts, const char *str, int len)
1590 {
1591 TokenSym *ts, **ptable;
1592 int i;
1593
1594 if (tok_ident >= SYM_FIRST_ANOM)
1595 error("memory full");
1596
1597 /* expand token table if needed */
1598 i = tok_ident - TOK_IDENT;
1599 if ((i % TOK_ALLOC_INCR) == 0) {
1600 ptable = tcc_realloc(table_ident, (i + TOK_ALLOC_INCR) * sizeof(TokenSym *));
1601 if (!ptable)
1602 error("memory full");
1603 table_ident = ptable;
1604 }
1605
1606 ts = tcc_malloc(sizeof(TokenSym) + len);
1607 table_ident[i] = ts;
1608 ts->tok = tok_ident++;
1609 ts->sym_define = NULL;
1610 ts->sym_label = NULL;
1611 ts->sym_struct = NULL;
1612 ts->sym_identifier = NULL;
1613 ts->len = len;
1614 ts->hash_next = NULL;
1615 memcpy(ts->str, str, len);
1616 ts->str[len] = '\0';
1617 *pts = ts;
1618 return ts;
1619 }
1620
1621 #define TOK_HASH_INIT 1
1622 #define TOK_HASH_FUNC(h, c) ((h) * 263 + (c))
1623
1624 /* find a token and add it if not found */
tok_alloc(const char * str,int len)1625 static TokenSym *tok_alloc(const char *str, int len)
1626 {
1627 TokenSym *ts, **pts;
1628 int i;
1629 unsigned int h;
1630
1631 h = TOK_HASH_INIT;
1632 for(i=0;i<len;i++)
1633 h = TOK_HASH_FUNC(h, ((unsigned char *)str)[i]);
1634 h &= (TOK_HASH_SIZE - 1);
1635
1636 pts = &hash_ident[h];
1637 for(;;) {
1638 ts = *pts;
1639 if (!ts)
1640 break;
1641 if (ts->len == len && !memcmp(ts->str, str, len))
1642 return ts;
1643 pts = &(ts->hash_next);
1644 }
1645 return tok_alloc_new(pts, str, len);
1646 }
1647
1648 /* CString handling */
1649
cstr_realloc(CString * cstr,int new_size)1650 static void cstr_realloc(CString *cstr, int new_size)
1651 {
1652 int size;
1653 void *data;
1654
1655 size = cstr->size_allocated;
1656 if (size == 0)
1657 size = 8; /* no need to allocate a too small first string */
1658 while (size < new_size)
1659 size = size * 2;
1660 data = tcc_realloc(cstr->data_allocated, size);
1661 if (!data)
1662 error("memory full");
1663 cstr->data_allocated = data;
1664 cstr->size_allocated = size;
1665 cstr->data = data;
1666 }
1667
1668 /* add a byte */
cstr_ccat(CString * cstr,int ch)1669 static inline void cstr_ccat(CString *cstr, int ch)
1670 {
1671 int size;
1672 size = cstr->size + 1;
1673 if (size > cstr->size_allocated)
1674 cstr_realloc(cstr, size);
1675 ((unsigned char *)cstr->data)[size - 1] = ch;
1676 cstr->size = size;
1677 }
1678
cstr_cat(CString * cstr,const char * str)1679 static void cstr_cat(CString *cstr, const char *str)
1680 {
1681 int c;
1682 for(;;) {
1683 c = *str;
1684 if (c == '\0')
1685 break;
1686 cstr_ccat(cstr, c);
1687 str++;
1688 }
1689 }
1690
1691 /* add a wide char */
cstr_wccat(CString * cstr,int ch)1692 static void cstr_wccat(CString *cstr, int ch)
1693 {
1694 int size;
1695 size = cstr->size + sizeof(nwchar_t);
1696 if (size > cstr->size_allocated)
1697 cstr_realloc(cstr, size);
1698 *(nwchar_t *)(((unsigned char *)cstr->data) + size - sizeof(nwchar_t)) = ch;
1699 cstr->size = size;
1700 }
1701
cstr_new(CString * cstr)1702 static void cstr_new(CString *cstr)
1703 {
1704 memset(cstr, 0, sizeof(CString));
1705 }
1706
1707 /* free string and reset it to NULL */
cstr_free(CString * cstr)1708 static void cstr_free(CString *cstr)
1709 {
1710 tcc_free(cstr->data_allocated);
1711 cstr_new(cstr);
1712 }
1713
1714 #define cstr_reset(cstr) cstr_free(cstr)
1715
1716 /* XXX: unicode ? */
add_char(CString * cstr,int c)1717 static void add_char(CString *cstr, int c)
1718 {
1719 if (c == '\'' || c == '\"' || c == '\\') {
1720 /* XXX: could be more precise if char or string */
1721 cstr_ccat(cstr, '\\');
1722 }
1723 if (c >= 32 && c <= 126) {
1724 cstr_ccat(cstr, c);
1725 } else {
1726 cstr_ccat(cstr, '\\');
1727 if (c == '\n') {
1728 cstr_ccat(cstr, 'n');
1729 } else {
1730 cstr_ccat(cstr, '0' + ((c >> 6) & 7));
1731 cstr_ccat(cstr, '0' + ((c >> 3) & 7));
1732 cstr_ccat(cstr, '0' + (c & 7));
1733 }
1734 }
1735 }
1736
1737 /* XXX: buffer overflow */
1738 /* XXX: float tokens */
get_tok_str(int v,CValue * cv)1739 char *get_tok_str(int v, CValue *cv)
1740 {
1741 static char buf[STRING_MAX_SIZE + 1];
1742 static CString cstr_buf;
1743 CString *cstr;
1744 unsigned char *q;
1745 char *p;
1746 int i, len;
1747
1748 /* NOTE: to go faster, we give a fixed buffer for small strings */
1749 cstr_reset(&cstr_buf);
1750 cstr_buf.data = buf;
1751 cstr_buf.size_allocated = sizeof(buf);
1752 p = buf;
1753
1754 switch(v) {
1755 case TOK_CINT:
1756 case TOK_CUINT:
1757 /* XXX: not quite exact, but only useful for testing */
1758 sprintf(p, "%u", cv->ui);
1759 break;
1760 case TOK_CLLONG:
1761 case TOK_CULLONG:
1762 /* XXX: not quite exact, but only useful for testing */
1763 sprintf(p, "%Lu", cv->ull);
1764 break;
1765 case TOK_CCHAR:
1766 case TOK_LCHAR:
1767 cstr_ccat(&cstr_buf, '\'');
1768 add_char(&cstr_buf, cv->i);
1769 cstr_ccat(&cstr_buf, '\'');
1770 cstr_ccat(&cstr_buf, '\0');
1771 break;
1772 case TOK_PPNUM:
1773 cstr = cv->cstr;
1774 len = cstr->size - 1;
1775 for(i=0;i<len;i++)
1776 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1777 cstr_ccat(&cstr_buf, '\0');
1778 break;
1779 case TOK_STR:
1780 case TOK_LSTR:
1781 cstr = cv->cstr;
1782 cstr_ccat(&cstr_buf, '\"');
1783 if (v == TOK_STR) {
1784 len = cstr->size - 1;
1785 for(i=0;i<len;i++)
1786 add_char(&cstr_buf, ((unsigned char *)cstr->data)[i]);
1787 } else {
1788 len = (cstr->size / sizeof(nwchar_t)) - 1;
1789 for(i=0;i<len;i++)
1790 add_char(&cstr_buf, ((nwchar_t *)cstr->data)[i]);
1791 }
1792 cstr_ccat(&cstr_buf, '\"');
1793 cstr_ccat(&cstr_buf, '\0');
1794 break;
1795 case TOK_LT:
1796 v = '<';
1797 goto addv;
1798 case TOK_GT:
1799 v = '>';
1800 goto addv;
1801 case TOK_DOTS:
1802 return strcpy(p, "...");
1803 case TOK_A_SHL:
1804 return strcpy(p, "<<=");
1805 case TOK_A_SAR:
1806 return strcpy(p, ">>=");
1807 default:
1808 if (v < TOK_IDENT) {
1809 /* search in two bytes table */
1810 q = tok_two_chars;
1811 while (*q) {
1812 if (q[2] == v) {
1813 *p++ = q[0];
1814 *p++ = q[1];
1815 *p = '\0';
1816 return buf;
1817 }
1818 q += 3;
1819 }
1820 addv:
1821 *p++ = v;
1822 *p = '\0';
1823 } else if (v < tok_ident) {
1824 return table_ident[v - TOK_IDENT]->str;
1825 } else if (v >= SYM_FIRST_ANOM) {
1826 /* special name for anonymous symbol */
1827 sprintf(p, "L.%u", v - SYM_FIRST_ANOM);
1828 } else {
1829 /* should never happen */
1830 return NULL;
1831 }
1832 break;
1833 }
1834 return cstr_buf.data;
1835 }
1836
1837 /* push, without hashing */
sym_push2(Sym ** ps,int v,int t,int c)1838 static Sym *sym_push2(Sym **ps, int v, int t, int c)
1839 {
1840 Sym *s;
1841 s = sym_malloc();
1842 s->v = v;
1843 s->type.t = t;
1844 s->c = c;
1845 s->next = NULL;
1846 /* add in stack */
1847 s->prev = *ps;
1848 *ps = s;
1849 return s;
1850 }
1851
1852 /* find a symbol and return its associated structure. 's' is the top
1853 of the symbol stack */
sym_find2(Sym * s,int v)1854 static Sym *sym_find2(Sym *s, int v)
1855 {
1856 while (s) {
1857 if (s->v == v)
1858 return s;
1859 s = s->prev;
1860 }
1861 return NULL;
1862 }
1863
1864 /* structure lookup */
struct_find(int v)1865 static inline Sym *struct_find(int v)
1866 {
1867 v -= TOK_IDENT;
1868 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1869 return NULL;
1870 return table_ident[v]->sym_struct;
1871 }
1872
1873 /* find an identifier */
sym_find(int v)1874 static inline Sym *sym_find(int v)
1875 {
1876 v -= TOK_IDENT;
1877 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
1878 return NULL;
1879 return table_ident[v]->sym_identifier;
1880 }
1881
1882 /* push a given symbol on the symbol stack */
sym_push(int v,CType * type,int r,int c)1883 static Sym *sym_push(int v, CType *type, int r, int c)
1884 {
1885 Sym *s, **ps;
1886 TokenSym *ts;
1887
1888 if (local_stack)
1889 ps = &local_stack;
1890 else
1891 ps = &global_stack;
1892 s = sym_push2(ps, v, type->t, c);
1893 s->type.ref = type->ref;
1894 s->r = r;
1895 /* don't record fields or anonymous symbols */
1896 /* XXX: simplify */
1897 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1898 /* record symbol in token array */
1899 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1900 if (v & SYM_STRUCT)
1901 ps = &ts->sym_struct;
1902 else
1903 ps = &ts->sym_identifier;
1904 s->prev_tok = *ps;
1905 *ps = s;
1906 }
1907 return s;
1908 }
1909
1910 /* push a global identifier */
global_identifier_push(int v,int t,int c)1911 static Sym *global_identifier_push(int v, int t, int c)
1912 {
1913 Sym *s, **ps;
1914 s = sym_push2(&global_stack, v, t, c);
1915 /* don't record anonymous symbol */
1916 if (v < SYM_FIRST_ANOM) {
1917 ps = &table_ident[v - TOK_IDENT]->sym_identifier;
1918 /* modify the top most local identifier, so that
1919 sym_identifier will point to 's' when popped */
1920 while (*ps != NULL)
1921 ps = &(*ps)->prev_tok;
1922 s->prev_tok = NULL;
1923 *ps = s;
1924 }
1925 return s;
1926 }
1927
1928 /* pop symbols until top reaches 'b' */
sym_pop(Sym ** ptop,Sym * b)1929 static void sym_pop(Sym **ptop, Sym *b)
1930 {
1931 Sym *s, *ss, **ps;
1932 TokenSym *ts;
1933 int v;
1934
1935 s = *ptop;
1936 while(s != b) {
1937 ss = s->prev;
1938 v = s->v;
1939 /* remove symbol in token array */
1940 /* XXX: simplify */
1941 if (!(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
1942 ts = table_ident[(v & ~SYM_STRUCT) - TOK_IDENT];
1943 if (v & SYM_STRUCT)
1944 ps = &ts->sym_struct;
1945 else
1946 ps = &ts->sym_identifier;
1947 *ps = s->prev_tok;
1948 }
1949 sym_free(s);
1950 s = ss;
1951 }
1952 *ptop = b;
1953 }
1954
1955 /* I/O layer */
1956
tcc_open(TCCState * s1,const char * filename)1957 BufferedFile *tcc_open(TCCState *s1, const char *filename)
1958 {
1959 int fd;
1960 BufferedFile *bf;
1961
1962 if (strcmp(filename, "-") == 0)
1963 fd = 0, filename = "stdin";
1964 else
1965 fd = open(filename, O_RDONLY | O_BINARY);
1966 if ((verbose == 2 && fd >= 0) || verbose == 3)
1967 printf("%s %*s%s\n", fd < 0 ? "nf":"->",
1968 (s1->include_stack_ptr - s1->include_stack), "", filename);
1969 if (fd < 0)
1970 return NULL;
1971 bf = tcc_malloc(sizeof(BufferedFile));
1972 bf->fd = fd;
1973 bf->buf_ptr = bf->buffer;
1974 bf->buf_end = bf->buffer;
1975 bf->buffer[0] = CH_EOB; /* put eob symbol */
1976 pstrcpy(bf->filename, sizeof(bf->filename), filename);
1977 #ifdef _WIN32
1978 normalize_slashes(bf->filename);
1979 #endif
1980 bf->line_num = 1;
1981 bf->ifndef_macro = 0;
1982 bf->ifdef_stack_ptr = s1->ifdef_stack_ptr;
1983 // printf("opening '%s'\n", filename);
1984 return bf;
1985 }
1986
tcc_close(BufferedFile * bf)1987 void tcc_close(BufferedFile *bf)
1988 {
1989 total_lines += bf->line_num;
1990 close(bf->fd);
1991 tcc_free(bf);
1992 }
1993
1994 /* fill input buffer and peek next char */
tcc_peekc_slow(BufferedFile * bf)1995 static int tcc_peekc_slow(BufferedFile *bf)
1996 {
1997 int len;
1998 /* only tries to read if really end of buffer */
1999 if (bf->buf_ptr >= bf->buf_end) {
2000 if (bf->fd != -1) {
2001 #if defined(PARSE_DEBUG)
2002 len = 8;
2003 #else
2004 len = IO_BUF_SIZE;
2005 #endif
2006 len = read(bf->fd, bf->buffer, len);
2007 if (len < 0)
2008 len = 0;
2009 } else {
2010 len = 0;
2011 }
2012 total_bytes += len;
2013 bf->buf_ptr = bf->buffer;
2014 bf->buf_end = bf->buffer + len;
2015 *bf->buf_end = CH_EOB;
2016 }
2017 if (bf->buf_ptr < bf->buf_end) {
2018 return bf->buf_ptr[0];
2019 } else {
2020 bf->buf_ptr = bf->buf_end;
2021 return CH_EOF;
2022 }
2023 }
2024
2025 /* return the current character, handling end of block if necessary
2026 (but not stray) */
handle_eob(void)2027 static int handle_eob(void)
2028 {
2029 return tcc_peekc_slow(file);
2030 }
2031
2032 /* read next char from current input file and handle end of input buffer */
inp(void)2033 static inline void inp(void)
2034 {
2035 ch = *(++(file->buf_ptr));
2036 /* end of buffer/file handling */
2037 if (ch == CH_EOB)
2038 ch = handle_eob();
2039 }
2040
2041 /* handle '\[\r]\n' */
handle_stray_noerror(void)2042 static int handle_stray_noerror(void)
2043 {
2044 while (ch == '\\') {
2045 inp();
2046 if (ch == '\n') {
2047 file->line_num++;
2048 inp();
2049 } else if (ch == '\r') {
2050 inp();
2051 if (ch != '\n')
2052 goto fail;
2053 file->line_num++;
2054 inp();
2055 } else {
2056 fail:
2057 return 1;
2058 }
2059 }
2060 return 0;
2061 }
2062
handle_stray(void)2063 static void handle_stray(void)
2064 {
2065 if (handle_stray_noerror())
2066 error("stray '\\' in program");
2067 }
2068
2069 /* skip the stray and handle the \\n case. Output an error if
2070 incorrect char after the stray */
handle_stray1(uint8_t * p)2071 static int handle_stray1(uint8_t *p)
2072 {
2073 int c;
2074
2075 if (p >= file->buf_end) {
2076 file->buf_ptr = p;
2077 c = handle_eob();
2078 p = file->buf_ptr;
2079 if (c == '\\')
2080 goto parse_stray;
2081 } else {
2082 parse_stray:
2083 file->buf_ptr = p;
2084 ch = *p;
2085 handle_stray();
2086 p = file->buf_ptr;
2087 c = *p;
2088 }
2089 return c;
2090 }
2091
2092 /* handle just the EOB case, but not stray */
2093 #define PEEKC_EOB(c, p)\
2094 {\
2095 p++;\
2096 c = *p;\
2097 if (c == '\\') {\
2098 file->buf_ptr = p;\
2099 c = handle_eob();\
2100 p = file->buf_ptr;\
2101 }\
2102 }
2103
2104 /* handle the complicated stray case */
2105 #define PEEKC(c, p)\
2106 {\
2107 p++;\
2108 c = *p;\
2109 if (c == '\\') {\
2110 c = handle_stray1(p);\
2111 p = file->buf_ptr;\
2112 }\
2113 }
2114
2115 /* input with '\[\r]\n' handling. Note that this function cannot
2116 handle other characters after '\', so you cannot call it inside
2117 strings or comments */
minp(void)2118 static void minp(void)
2119 {
2120 inp();
2121 if (ch == '\\')
2122 handle_stray();
2123 }
2124
2125
2126 /* single line C++ comments */
parse_line_comment(uint8_t * p)2127 static uint8_t *parse_line_comment(uint8_t *p)
2128 {
2129 int c;
2130
2131 p++;
2132 for(;;) {
2133 c = *p;
2134 redo:
2135 if (c == '\n' || c == CH_EOF) {
2136 break;
2137 } else if (c == '\\') {
2138 file->buf_ptr = p;
2139 c = handle_eob();
2140 p = file->buf_ptr;
2141 if (c == '\\') {
2142 PEEKC_EOB(c, p);
2143 if (c == '\n') {
2144 file->line_num++;
2145 PEEKC_EOB(c, p);
2146 } else if (c == '\r') {
2147 PEEKC_EOB(c, p);
2148 if (c == '\n') {
2149 file->line_num++;
2150 PEEKC_EOB(c, p);
2151 }
2152 }
2153 } else {
2154 goto redo;
2155 }
2156 } else {
2157 p++;
2158 }
2159 }
2160 return p;
2161 }
2162
2163 /* C comments */
parse_comment(uint8_t * p)2164 static uint8_t *parse_comment(uint8_t *p)
2165 {
2166 int c;
2167
2168 p++;
2169 for(;;) {
2170 /* fast skip loop */
2171 for(;;) {
2172 c = *p;
2173 if (c == '\n' || c == '*' || c == '\\')
2174 break;
2175 p++;
2176 c = *p;
2177 if (c == '\n' || c == '*' || c == '\\')
2178 break;
2179 p++;
2180 }
2181 /* now we can handle all the cases */
2182 if (c == '\n') {
2183 file->line_num++;
2184 p++;
2185 } else if (c == '*') {
2186 p++;
2187 for(;;) {
2188 c = *p;
2189 if (c == '*') {
2190 p++;
2191 } else if (c == '/') {
2192 goto end_of_comment;
2193 } else if (c == '\\') {
2194 file->buf_ptr = p;
2195 c = handle_eob();
2196 p = file->buf_ptr;
2197 if (c == '\\') {
2198 /* skip '\[\r]\n', otherwise just skip the stray */
2199 while (c == '\\') {
2200 PEEKC_EOB(c, p);
2201 if (c == '\n') {
2202 file->line_num++;
2203 PEEKC_EOB(c, p);
2204 } else if (c == '\r') {
2205 PEEKC_EOB(c, p);
2206 if (c == '\n') {
2207 file->line_num++;
2208 PEEKC_EOB(c, p);
2209 }
2210 } else {
2211 goto after_star;
2212 }
2213 }
2214 }
2215 } else {
2216 break;
2217 }
2218 }
2219 after_star: ;
2220 } else {
2221 /* stray, eob or eof */
2222 file->buf_ptr = p;
2223 c = handle_eob();
2224 p = file->buf_ptr;
2225 if (c == CH_EOF) {
2226 error("unexpected end of file in comment");
2227 } else if (c == '\\') {
2228 p++;
2229 }
2230 }
2231 }
2232 end_of_comment:
2233 p++;
2234 return p;
2235 }
2236
2237 #define cinp minp
2238
2239 /* space exlcuding newline */
is_space(int ch)2240 static inline int is_space(int ch)
2241 {
2242 return ch == ' ' || ch == '\t' || ch == '\v' || ch == '\f' || ch == '\r';
2243 }
2244
skip_spaces(void)2245 static inline void skip_spaces(void)
2246 {
2247 while (is_space(ch))
2248 cinp();
2249 }
2250
2251 /* parse a string without interpreting escapes */
parse_pp_string(uint8_t * p,int sep,CString * str)2252 static uint8_t *parse_pp_string(uint8_t *p,
2253 int sep, CString *str)
2254 {
2255 int c;
2256 p++;
2257 for(;;) {
2258 c = *p;
2259 if (c == sep) {
2260 break;
2261 } else if (c == '\\') {
2262 file->buf_ptr = p;
2263 c = handle_eob();
2264 p = file->buf_ptr;
2265 if (c == CH_EOF) {
2266 unterminated_string:
2267 /* XXX: indicate line number of start of string */
2268 error("missing terminating %c character", sep);
2269 } else if (c == '\\') {
2270 /* escape : just skip \[\r]\n */
2271 PEEKC_EOB(c, p);
2272 if (c == '\n') {
2273 file->line_num++;
2274 p++;
2275 } else if (c == '\r') {
2276 PEEKC_EOB(c, p);
2277 if (c != '\n')
2278 expect("'\n' after '\r'");
2279 file->line_num++;
2280 p++;
2281 } else if (c == CH_EOF) {
2282 goto unterminated_string;
2283 } else {
2284 if (str) {
2285 cstr_ccat(str, '\\');
2286 cstr_ccat(str, c);
2287 }
2288 p++;
2289 }
2290 }
2291 } else if (c == '\n') {
2292 file->line_num++;
2293 goto add_char;
2294 } else if (c == '\r') {
2295 PEEKC_EOB(c, p);
2296 if (c != '\n') {
2297 if (str)
2298 cstr_ccat(str, '\r');
2299 } else {
2300 file->line_num++;
2301 goto add_char;
2302 }
2303 } else {
2304 add_char:
2305 if (str)
2306 cstr_ccat(str, c);
2307 p++;
2308 }
2309 }
2310 p++;
2311 return p;
2312 }
2313
2314 /* skip block of text until #else, #elif or #endif. skip also pairs of
2315 #if/#endif */
preprocess_skip(void)2316 void preprocess_skip(void)
2317 {
2318 int a, start_of_line, c, in_warn_or_error;
2319 uint8_t *p;
2320
2321 p = file->buf_ptr;
2322 a = 0;
2323 redo_start:
2324 start_of_line = 1;
2325 in_warn_or_error = 0;
2326 for(;;) {
2327 redo_no_start:
2328 c = *p;
2329 switch(c) {
2330 case ' ':
2331 case '\t':
2332 case '\f':
2333 case '\v':
2334 case '\r':
2335 p++;
2336 goto redo_no_start;
2337 case '\n':
2338 file->line_num++;
2339 p++;
2340 goto redo_start;
2341 case '\\':
2342 file->buf_ptr = p;
2343 c = handle_eob();
2344 if (c == CH_EOF) {
2345 expect("#endif");
2346 } else if (c == '\\') {
2347 ch = file->buf_ptr[0];
2348 handle_stray_noerror();
2349 }
2350 p = file->buf_ptr;
2351 goto redo_no_start;
2352 /* skip strings */
2353 case '\"':
2354 case '\'':
2355 if (in_warn_or_error)
2356 goto _default;
2357 p = parse_pp_string(p, c, NULL);
2358 break;
2359 /* skip comments */
2360 case '/':
2361 if (in_warn_or_error)
2362 goto _default;
2363 file->buf_ptr = p;
2364 ch = *p;
2365 minp();
2366 p = file->buf_ptr;
2367 if (ch == '*') {
2368 p = parse_comment(p);
2369 } else if (ch == '/') {
2370 p = parse_line_comment(p);
2371 }
2372 break;
2373 case '#':
2374 p++;
2375 if (start_of_line) {
2376 file->buf_ptr = p;
2377 next_nomacro();
2378 p = file->buf_ptr;
2379 if (a == 0 &&
2380 (tok == TOK_ELSE || tok == TOK_ELIF || tok == TOK_ENDIF))
2381 goto the_end;
2382 if (tok == TOK_IF || tok == TOK_IFDEF || tok == TOK_IFNDEF)
2383 a++;
2384 else if (tok == TOK_ENDIF)
2385 a--;
2386 else if( tok == TOK_ERROR || tok == TOK_WARNING)
2387 in_warn_or_error = 1;
2388 }
2389 break;
2390 _default:
2391 default:
2392 p++;
2393 break;
2394 }
2395 start_of_line = 0;
2396 }
2397 the_end: ;
2398 file->buf_ptr = p;
2399 }
2400
2401 /* ParseState handling */
2402
2403 /* XXX: currently, no include file info is stored. Thus, we cannot display
2404 accurate messages if the function or data definition spans multiple
2405 files */
2406
2407 /* save current parse state in 's' */
save_parse_state(ParseState * s)2408 void save_parse_state(ParseState *s)
2409 {
2410 s->line_num = file->line_num;
2411 s->macro_ptr = macro_ptr;
2412 s->tok = tok;
2413 s->tokc = tokc;
2414 }
2415
2416 /* restore parse state from 's' */
restore_parse_state(ParseState * s)2417 void restore_parse_state(ParseState *s)
2418 {
2419 file->line_num = s->line_num;
2420 macro_ptr = s->macro_ptr;
2421 tok = s->tok;
2422 tokc = s->tokc;
2423 }
2424
2425 /* return the number of additional 'ints' necessary to store the
2426 token */
tok_ext_size(int t)2427 static inline int tok_ext_size(int t)
2428 {
2429 switch(t) {
2430 /* 4 bytes */
2431 case TOK_CINT:
2432 case TOK_CUINT:
2433 case TOK_CCHAR:
2434 case TOK_LCHAR:
2435 case TOK_CFLOAT:
2436 case TOK_LINENUM:
2437 return 1;
2438 case TOK_STR:
2439 case TOK_LSTR:
2440 case TOK_PPNUM:
2441 error("unsupported token");
2442 return 1;
2443 case TOK_CDOUBLE:
2444 case TOK_CLLONG:
2445 case TOK_CULLONG:
2446 return 2;
2447 case TOK_CLDOUBLE:
2448 return LDOUBLE_SIZE / 4;
2449 default:
2450 return 0;
2451 }
2452 }
2453
2454 /* token string handling */
2455
tok_str_new(TokenString * s)2456 static inline void tok_str_new(TokenString *s)
2457 {
2458 s->str = NULL;
2459 s->len = 0;
2460 s->allocated_len = 0;
2461 s->last_line_num = -1;
2462 }
2463
tok_str_free(int * str)2464 static void tok_str_free(int *str)
2465 {
2466 tcc_free(str);
2467 }
2468
tok_str_realloc(TokenString * s)2469 static int *tok_str_realloc(TokenString *s)
2470 {
2471 int *str, len;
2472
2473 if (s->allocated_len == 0) {
2474 len = 8;
2475 } else {
2476 len = s->allocated_len * 2;
2477 }
2478 str = tcc_realloc(s->str, len * sizeof(int));
2479 if (!str)
2480 error("memory full");
2481 s->allocated_len = len;
2482 s->str = str;
2483 return str;
2484 }
2485
tok_str_add(TokenString * s,int t)2486 static void tok_str_add(TokenString *s, int t)
2487 {
2488 int len, *str;
2489
2490 len = s->len;
2491 str = s->str;
2492 if (len >= s->allocated_len)
2493 str = tok_str_realloc(s);
2494 str[len++] = t;
2495 s->len = len;
2496 }
2497
tok_str_add2(TokenString * s,int t,CValue * cv)2498 static void tok_str_add2(TokenString *s, int t, CValue *cv)
2499 {
2500 int len, *str;
2501
2502 len = s->len;
2503 str = s->str;
2504
2505 /* allocate space for worst case */
2506 if (len + TOK_MAX_SIZE > s->allocated_len)
2507 str = tok_str_realloc(s);
2508 str[len++] = t;
2509 switch(t) {
2510 case TOK_CINT:
2511 case TOK_CUINT:
2512 case TOK_CCHAR:
2513 case TOK_LCHAR:
2514 case TOK_CFLOAT:
2515 case TOK_LINENUM:
2516 str[len++] = cv->tab[0];
2517 break;
2518 case TOK_PPNUM:
2519 case TOK_STR:
2520 case TOK_LSTR:
2521 {
2522 int nb_words;
2523 CString *cstr;
2524
2525 nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
2526 while ((len + nb_words) > s->allocated_len)
2527 str = tok_str_realloc(s);
2528 cstr = (CString *)(str + len);
2529 cstr->data = NULL;
2530 cstr->size = cv->cstr->size;
2531 cstr->data_allocated = NULL;
2532 cstr->size_allocated = cstr->size;
2533 memcpy((char *)cstr + sizeof(CString),
2534 cv->cstr->data, cstr->size);
2535 len += nb_words;
2536 }
2537 break;
2538 case TOK_CDOUBLE:
2539 case TOK_CLLONG:
2540 case TOK_CULLONG:
2541 #if LDOUBLE_SIZE == 8
2542 case TOK_CLDOUBLE:
2543 #endif
2544 str[len++] = cv->tab[0];
2545 str[len++] = cv->tab[1];
2546 break;
2547 #if LDOUBLE_SIZE == 12
2548 case TOK_CLDOUBLE:
2549 str[len++] = cv->tab[0];
2550 str[len++] = cv->tab[1];
2551 str[len++] = cv->tab[2];
2552 #elif LDOUBLE_SIZE != 8
2553 #error add long double size support
2554 #endif
2555 break;
2556 default:
2557 break;
2558 }
2559 s->len = len;
2560 }
2561
2562 /* add the current parse token in token string 's' */
tok_str_add_tok(TokenString * s)2563 static void tok_str_add_tok(TokenString *s)
2564 {
2565 CValue cval;
2566
2567 /* save line number info */
2568 if (file->line_num != s->last_line_num) {
2569 s->last_line_num = file->line_num;
2570 cval.i = s->last_line_num;
2571 tok_str_add2(s, TOK_LINENUM, &cval);
2572 }
2573 tok_str_add2(s, tok, &tokc);
2574 }
2575
2576 #if LDOUBLE_SIZE == 12
2577 #define LDOUBLE_GET(p, cv) \
2578 cv.tab[0] = p[0]; \
2579 cv.tab[1] = p[1]; \
2580 cv.tab[2] = p[2];
2581 #elif LDOUBLE_SIZE == 8
2582 #define LDOUBLE_GET(p, cv) \
2583 cv.tab[0] = p[0]; \
2584 cv.tab[1] = p[1];
2585 #else
2586 #error add long double size support
2587 #endif
2588
2589
2590 /* get a token from an integer array and increment pointer
2591 accordingly. we code it as a macro to avoid pointer aliasing. */
2592 #define TOK_GET(t, p, cv) \
2593 { \
2594 t = *p++; \
2595 switch(t) { \
2596 case TOK_CINT: \
2597 case TOK_CUINT: \
2598 case TOK_CCHAR: \
2599 case TOK_LCHAR: \
2600 case TOK_CFLOAT: \
2601 case TOK_LINENUM: \
2602 cv.tab[0] = *p++; \
2603 break; \
2604 case TOK_STR: \
2605 case TOK_LSTR: \
2606 case TOK_PPNUM: \
2607 cv.cstr = (CString *)p; \
2608 cv.cstr->data = (char *)p + sizeof(CString);\
2609 p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
2610 break; \
2611 case TOK_CDOUBLE: \
2612 case TOK_CLLONG: \
2613 case TOK_CULLONG: \
2614 cv.tab[0] = p[0]; \
2615 cv.tab[1] = p[1]; \
2616 p += 2; \
2617 break; \
2618 case TOK_CLDOUBLE: \
2619 LDOUBLE_GET(p, cv); \
2620 p += LDOUBLE_SIZE / 4; \
2621 break; \
2622 default: \
2623 break; \
2624 } \
2625 }
2626
2627 /* defines handling */
define_push(int v,int macro_type,int * str,Sym * first_arg)2628 static inline void define_push(int v, int macro_type, int *str, Sym *first_arg)
2629 {
2630 Sym *s;
2631
2632 s = sym_push2(&define_stack, v, macro_type, (int)str);
2633 s->next = first_arg;
2634 table_ident[v - TOK_IDENT]->sym_define = s;
2635 }
2636
2637 /* undefined a define symbol. Its name is just set to zero */
define_undef(Sym * s)2638 static void define_undef(Sym *s)
2639 {
2640 int v;
2641 v = s->v;
2642 if (v >= TOK_IDENT && v < tok_ident)
2643 table_ident[v - TOK_IDENT]->sym_define = NULL;
2644 s->v = 0;
2645 }
2646
define_find(int v)2647 static inline Sym *define_find(int v)
2648 {
2649 v -= TOK_IDENT;
2650 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2651 return NULL;
2652 return table_ident[v]->sym_define;
2653 }
2654
2655 /* free define stack until top reaches 'b' */
free_defines(Sym * b)2656 static void free_defines(Sym *b)
2657 {
2658 Sym *top, *top1;
2659 int v;
2660
2661 top = define_stack;
2662 while (top != b) {
2663 top1 = top->prev;
2664 /* do not free args or predefined defines */
2665 if (top->c)
2666 tok_str_free((int *)top->c);
2667 v = top->v;
2668 if (v >= TOK_IDENT && v < tok_ident)
2669 table_ident[v - TOK_IDENT]->sym_define = NULL;
2670 sym_free(top);
2671 top = top1;
2672 }
2673 define_stack = b;
2674 }
2675
2676 /* label lookup */
label_find(int v)2677 static Sym *label_find(int v)
2678 {
2679 v -= TOK_IDENT;
2680 if ((unsigned)v >= (unsigned)(tok_ident - TOK_IDENT))
2681 return NULL;
2682 return table_ident[v]->sym_label;
2683 }
2684
label_push(Sym ** ptop,int v,int flags)2685 static Sym *label_push(Sym **ptop, int v, int flags)
2686 {
2687 Sym *s, **ps;
2688 s = sym_push2(ptop, v, 0, 0);
2689 s->r = flags;
2690 ps = &table_ident[v - TOK_IDENT]->sym_label;
2691 if (ptop == &global_label_stack) {
2692 /* modify the top most local identifier, so that
2693 sym_identifier will point to 's' when popped */
2694 while (*ps != NULL)
2695 ps = &(*ps)->prev_tok;
2696 }
2697 s->prev_tok = *ps;
2698 *ps = s;
2699 return s;
2700 }
2701
2702 /* pop labels until element last is reached. Look if any labels are
2703 undefined. Define symbols if '&&label' was used. */
label_pop(Sym ** ptop,Sym * slast)2704 static void label_pop(Sym **ptop, Sym *slast)
2705 {
2706 Sym *s, *s1;
2707 for(s = *ptop; s != slast; s = s1) {
2708 s1 = s->prev;
2709 if (s->r == LABEL_DECLARED) {
2710 warning("label '%s' declared but not used", get_tok_str(s->v, NULL));
2711 } else if (s->r == LABEL_FORWARD) {
2712 error("label '%s' used but not defined",
2713 get_tok_str(s->v, NULL));
2714 } else {
2715 if (s->c) {
2716 /* define corresponding symbol. A size of
2717 1 is put. */
2718 put_extern_sym(s, cur_text_section, (long)s->next, 1);
2719 }
2720 }
2721 /* remove label */
2722 table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
2723 sym_free(s);
2724 }
2725 *ptop = slast;
2726 }
2727
2728 /* eval an expression for #if/#elif */
expr_preprocess(void)2729 static int expr_preprocess(void)
2730 {
2731 int c, t;
2732 TokenString str;
2733
2734 tok_str_new(&str);
2735 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2736 next(); /* do macro subst */
2737 if (tok == TOK_DEFINED) {
2738 next_nomacro();
2739 t = tok;
2740 if (t == '(')
2741 next_nomacro();
2742 c = define_find(tok) != 0;
2743 if (t == '(')
2744 next_nomacro();
2745 tok = TOK_CINT;
2746 tokc.i = c;
2747 } else if (tok >= TOK_IDENT) {
2748 /* if undefined macro */
2749 tok = TOK_CINT;
2750 tokc.i = 0;
2751 }
2752 tok_str_add_tok(&str);
2753 }
2754 tok_str_add(&str, -1); /* simulate end of file */
2755 tok_str_add(&str, 0);
2756 /* now evaluate C constant expression */
2757 macro_ptr = str.str;
2758 next();
2759 c = expr_const();
2760 macro_ptr = NULL;
2761 tok_str_free(str.str);
2762 return c != 0;
2763 }
2764
2765 #if defined(PARSE_DEBUG) || defined(PP_DEBUG)
tok_print(int * str)2766 static void tok_print(int *str)
2767 {
2768 int t;
2769 CValue cval;
2770
2771 while (1) {
2772 TOK_GET(t, str, cval);
2773 if (!t)
2774 break;
2775 printf(" %s", get_tok_str(t, &cval));
2776 }
2777 printf("\n");
2778 }
2779 #endif
2780
2781 /* parse after #define */
parse_define(void)2782 static void parse_define(void)
2783 {
2784 Sym *s, *first, **ps;
2785 int v, t, varg, is_vaargs, c;
2786 TokenString str;
2787
2788 v = tok;
2789 if (v < TOK_IDENT)
2790 error("invalid macro name '%s'", get_tok_str(tok, &tokc));
2791 /* XXX: should check if same macro (ANSI) */
2792 first = NULL;
2793 t = MACRO_OBJ;
2794 /* '(' must be just after macro definition for MACRO_FUNC */
2795 c = file->buf_ptr[0];
2796 if (c == '\\')
2797 c = handle_stray1(file->buf_ptr);
2798 if (c == '(') {
2799 next_nomacro();
2800 next_nomacro();
2801 ps = &first;
2802 while (tok != ')') {
2803 varg = tok;
2804 next_nomacro();
2805 is_vaargs = 0;
2806 if (varg == TOK_DOTS) {
2807 varg = TOK___VA_ARGS__;
2808 is_vaargs = 1;
2809 } else if (tok == TOK_DOTS && gnu_ext) {
2810 is_vaargs = 1;
2811 next_nomacro();
2812 }
2813 if (varg < TOK_IDENT)
2814 error("badly punctuated parameter list");
2815 s = sym_push2(&define_stack, varg | SYM_FIELD, is_vaargs, 0);
2816 *ps = s;
2817 ps = &s->next;
2818 if (tok != ',')
2819 break;
2820 next_nomacro();
2821 }
2822 t = MACRO_FUNC;
2823 }
2824 tok_str_new(&str);
2825 next_nomacro();
2826 /* EOF testing necessary for '-D' handling */
2827 while (tok != TOK_LINEFEED && tok != TOK_EOF) {
2828 tok_str_add2(&str, tok, &tokc);
2829 next_nomacro();
2830 }
2831 tok_str_add(&str, 0);
2832 #ifdef PP_DEBUG
2833 printf("define %s %d: ", get_tok_str(v, NULL), t);
2834 tok_print(str.str);
2835 #endif
2836 define_push(v, t, str.str, first);
2837 }
2838
hash_cached_include(int type,const char * filename)2839 static inline int hash_cached_include(int type, const char *filename)
2840 {
2841 const unsigned char *s;
2842 unsigned int h;
2843
2844 h = TOK_HASH_INIT;
2845 h = TOK_HASH_FUNC(h, type);
2846 s = filename;
2847 while (*s) {
2848 h = TOK_HASH_FUNC(h, *s);
2849 s++;
2850 }
2851 h &= (CACHED_INCLUDES_HASH_SIZE - 1);
2852 return h;
2853 }
2854
2855 /* XXX: use a token or a hash table to accelerate matching ? */
search_cached_include(TCCState * s1,int type,const char * filename)2856 static CachedInclude *search_cached_include(TCCState *s1,
2857 int type, const char *filename)
2858 {
2859 CachedInclude *e;
2860 int i, h;
2861 h = hash_cached_include(type, filename);
2862 i = s1->cached_includes_hash[h];
2863 for(;;) {
2864 if (i == 0)
2865 break;
2866 e = s1->cached_includes[i - 1];
2867 if (e->type == type && !strcmp(e->filename, filename))
2868 return e;
2869 i = e->hash_next;
2870 }
2871 return NULL;
2872 }
2873
add_cached_include(TCCState * s1,int type,const char * filename,int ifndef_macro)2874 static inline void add_cached_include(TCCState *s1, int type,
2875 const char *filename, int ifndef_macro)
2876 {
2877 CachedInclude *e;
2878 int h;
2879
2880 if (search_cached_include(s1, type, filename))
2881 return;
2882 #ifdef INC_DEBUG
2883 printf("adding cached '%s' %s\n", filename, get_tok_str(ifndef_macro, NULL));
2884 #endif
2885 e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
2886 if (!e)
2887 return;
2888 e->type = type;
2889 strcpy(e->filename, filename);
2890 e->ifndef_macro = ifndef_macro;
2891 dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
2892 /* add in hash table */
2893 h = hash_cached_include(type, filename);
2894 e->hash_next = s1->cached_includes_hash[h];
2895 s1->cached_includes_hash[h] = s1->nb_cached_includes;
2896 }
2897
pragma_parse(TCCState * s1)2898 static void pragma_parse(TCCState *s1)
2899 {
2900 int val;
2901
2902 next();
2903 if (tok == TOK_pack) {
2904 /*
2905 This may be:
2906 #pragma pack(1) // set
2907 #pragma pack() // reset to default
2908 #pragma pack(push,1) // push & set
2909 #pragma pack(pop) // restore previous
2910 */
2911 next();
2912 skip('(');
2913 if (tok == TOK_ASM_pop) {
2914 next();
2915 if (s1->pack_stack_ptr <= s1->pack_stack) {
2916 stk_error:
2917 error("out of pack stack");
2918 }
2919 s1->pack_stack_ptr--;
2920 } else {
2921 val = 0;
2922 if (tok != ')') {
2923 if (tok == TOK_ASM_push) {
2924 next();
2925 if (s1->pack_stack_ptr >= s1->pack_stack + PACK_STACK_SIZE - 1)
2926 goto stk_error;
2927 s1->pack_stack_ptr++;
2928 skip(',');
2929 }
2930 if (tok != TOK_CINT) {
2931 pack_error:
2932 error("invalid pack pragma");
2933 }
2934 val = tokc.i;
2935 if (val < 1 || val > 16 || (val & (val - 1)) != 0)
2936 goto pack_error;
2937 next();
2938 }
2939 *s1->pack_stack_ptr = val;
2940 skip(')');
2941 }
2942 }
2943 }
2944
2945 /* is_bof is true if first non space token at beginning of file */
preprocess(int is_bof)2946 static void preprocess(int is_bof)
2947 {
2948 TCCState *s1 = tcc_state;
2949 int size, i, c, n, saved_parse_flags;
2950 char buf[1024], *q;
2951 char buf1[1024];
2952 BufferedFile *f;
2953 Sym *s;
2954 CachedInclude *e;
2955
2956 saved_parse_flags = parse_flags;
2957 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM |
2958 PARSE_FLAG_LINEFEED;
2959 next_nomacro();
2960 redo:
2961 switch(tok) {
2962 case TOK_DEFINE:
2963 next_nomacro();
2964 parse_define();
2965 break;
2966 case TOK_UNDEF:
2967 next_nomacro();
2968 s = define_find(tok);
2969 /* undefine symbol by putting an invalid name */
2970 if (s)
2971 define_undef(s);
2972 break;
2973 case TOK_INCLUDE:
2974 case TOK_INCLUDE_NEXT:
2975 ch = file->buf_ptr[0];
2976 /* XXX: incorrect if comments : use next_nomacro with a special mode */
2977 skip_spaces();
2978 if (ch == '<') {
2979 c = '>';
2980 goto read_name;
2981 } else if (ch == '\"') {
2982 c = ch;
2983 read_name:
2984 inp();
2985 q = buf;
2986 while (ch != c && ch != '\n' && ch != CH_EOF) {
2987 if ((q - buf) < sizeof(buf) - 1)
2988 *q++ = ch;
2989 if (ch == '\\') {
2990 if (handle_stray_noerror() == 0)
2991 --q;
2992 } else
2993 inp();
2994 }
2995 *q = '\0';
2996 minp();
2997 #if 0
2998 /* eat all spaces and comments after include */
2999 /* XXX: slightly incorrect */
3000 while (ch1 != '\n' && ch1 != CH_EOF)
3001 inp();
3002 #endif
3003 } else {
3004 /* computed #include : either we have only strings or
3005 we have anything enclosed in '<>' */
3006 next();
3007 buf[0] = '\0';
3008 if (tok == TOK_STR) {
3009 while (tok != TOK_LINEFEED) {
3010 if (tok != TOK_STR) {
3011 include_syntax:
3012 error("'#include' expects \"FILENAME\" or <FILENAME>");
3013 }
3014 pstrcat(buf, sizeof(buf), (char *)tokc.cstr->data);
3015 next();
3016 }
3017 c = '\"';
3018 } else {
3019 int len;
3020 while (tok != TOK_LINEFEED) {
3021 pstrcat(buf, sizeof(buf), get_tok_str(tok, &tokc));
3022 next();
3023 }
3024 len = strlen(buf);
3025 /* check syntax and remove '<>' */
3026 if (len < 2 || buf[0] != '<' || buf[len - 1] != '>')
3027 goto include_syntax;
3028 memmove(buf, buf + 1, len - 2);
3029 buf[len - 2] = '\0';
3030 c = '>';
3031 }
3032 }
3033
3034 e = search_cached_include(s1, c, buf);
3035 if (e && define_find(e->ifndef_macro)) {
3036 /* no need to parse the include because the 'ifndef macro'
3037 is defined */
3038 #ifdef INC_DEBUG
3039 printf("%s: skipping %s\n", file->filename, buf);
3040 #endif
3041 } else {
3042 if (s1->include_stack_ptr >= s1->include_stack + INCLUDE_STACK_SIZE)
3043 error("#include recursion too deep");
3044 /* push current file in stack */
3045 /* XXX: fix current line init */
3046 *s1->include_stack_ptr++ = file;
3047 if (c == '\"') {
3048 /* first search in current dir if "header.h" */
3049 size = tcc_basename(file->filename) - file->filename;
3050 if (size > sizeof(buf1) - 1)
3051 size = sizeof(buf1) - 1;
3052 memcpy(buf1, file->filename, size);
3053 buf1[size] = '\0';
3054 pstrcat(buf1, sizeof(buf1), buf);
3055 f = tcc_open(s1, buf1);
3056 if (f) {
3057 if (tok == TOK_INCLUDE_NEXT)
3058 tok = TOK_INCLUDE;
3059 else
3060 goto found;
3061 }
3062 }
3063 /* now search in all the include paths */
3064 n = s1->nb_include_paths + s1->nb_sysinclude_paths;
3065 for(i = 0; i < n; i++) {
3066 const char *path;
3067 if (i < s1->nb_include_paths)
3068 path = s1->include_paths[i];
3069 else
3070 path = s1->sysinclude_paths[i - s1->nb_include_paths];
3071 pstrcpy(buf1, sizeof(buf1), path);
3072 pstrcat(buf1, sizeof(buf1), "/");
3073 pstrcat(buf1, sizeof(buf1), buf);
3074 f = tcc_open(s1, buf1);
3075 if (f) {
3076 if (tok == TOK_INCLUDE_NEXT)
3077 tok = TOK_INCLUDE;
3078 else
3079 goto found;
3080 }
3081 }
3082 --s1->include_stack_ptr;
3083 error("include file '%s' not found", buf);
3084 break;
3085 found:
3086 #ifdef INC_DEBUG
3087 printf("%s: including %s\n", file->filename, buf1);
3088 #endif
3089 f->inc_type = c;
3090 pstrcpy(f->inc_filename, sizeof(f->inc_filename), buf);
3091 file = f;
3092 /* add include file debug info */
3093 if (do_debug) {
3094 put_stabs(file->filename, N_BINCL, 0, 0, 0);
3095 }
3096 tok_flags |= TOK_FLAG_BOF | TOK_FLAG_BOL;
3097 ch = file->buf_ptr[0];
3098 goto the_end;
3099 }
3100 break;
3101 case TOK_IFNDEF:
3102 c = 1;
3103 goto do_ifdef;
3104 case TOK_IF:
3105 c = expr_preprocess();
3106 goto do_if;
3107 case TOK_IFDEF:
3108 c = 0;
3109 do_ifdef:
3110 next_nomacro();
3111 if (tok < TOK_IDENT)
3112 error("invalid argument for '#if%sdef'", c ? "n" : "");
3113 if (is_bof) {
3114 if (c) {
3115 #ifdef INC_DEBUG
3116 printf("#ifndef %s\n", get_tok_str(tok, NULL));
3117 #endif
3118 file->ifndef_macro = tok;
3119 }
3120 }
3121 c = (define_find(tok) != 0) ^ c;
3122 do_if:
3123 if (s1->ifdef_stack_ptr >= s1->ifdef_stack + IFDEF_STACK_SIZE)
3124 error("memory full");
3125 *s1->ifdef_stack_ptr++ = c;
3126 goto test_skip;
3127 case TOK_ELSE:
3128 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3129 error("#else without matching #if");
3130 if (s1->ifdef_stack_ptr[-1] & 2)
3131 error("#else after #else");
3132 c = (s1->ifdef_stack_ptr[-1] ^= 3);
3133 goto test_skip;
3134 case TOK_ELIF:
3135 if (s1->ifdef_stack_ptr == s1->ifdef_stack)
3136 error("#elif without matching #if");
3137 c = s1->ifdef_stack_ptr[-1];
3138 if (c > 1)
3139 error("#elif after #else");
3140 /* last #if/#elif expression was true: we skip */
3141 if (c == 1)
3142 goto skip;
3143 c = expr_preprocess();
3144 s1->ifdef_stack_ptr[-1] = c;
3145 test_skip:
3146 if (!(c & 1)) {
3147 skip:
3148 preprocess_skip();
3149 is_bof = 0;
3150 goto redo;
3151 }
3152 break;
3153 case TOK_ENDIF:
3154 if (s1->ifdef_stack_ptr <= file->ifdef_stack_ptr)
3155 error("#endif without matching #if");
3156 s1->ifdef_stack_ptr--;
3157 /* '#ifndef macro' was at the start of file. Now we check if
3158 an '#endif' is exactly at the end of file */
3159 if (file->ifndef_macro &&
3160 s1->ifdef_stack_ptr == file->ifdef_stack_ptr) {
3161 file->ifndef_macro_saved = file->ifndef_macro;
3162 /* need to set to zero to avoid false matches if another
3163 #ifndef at middle of file */
3164 file->ifndef_macro = 0;
3165 while (tok != TOK_LINEFEED)
3166 next_nomacro();
3167 tok_flags |= TOK_FLAG_ENDIF;
3168 goto the_end;
3169 }
3170 break;
3171 case TOK_LINE:
3172 next();
3173 if (tok != TOK_CINT)
3174 error("#line");
3175 file->line_num = tokc.i - 1; /* the line number will be incremented after */
3176 next();
3177 if (tok != TOK_LINEFEED) {
3178 if (tok != TOK_STR)
3179 error("#line");
3180 pstrcpy(file->filename, sizeof(file->filename),
3181 (char *)tokc.cstr->data);
3182 }
3183 break;
3184 case TOK_ERROR:
3185 case TOK_WARNING:
3186 c = tok;
3187 ch = file->buf_ptr[0];
3188 skip_spaces();
3189 q = buf;
3190 while (ch != '\n' && ch != CH_EOF) {
3191 if ((q - buf) < sizeof(buf) - 1)
3192 *q++ = ch;
3193 if (ch == '\\') {
3194 if (handle_stray_noerror() == 0)
3195 --q;
3196 } else
3197 inp();
3198 }
3199 *q = '\0';
3200 if (c == TOK_ERROR)
3201 error("#error %s", buf);
3202 else
3203 warning("#warning %s", buf);
3204 break;
3205 case TOK_PRAGMA:
3206 pragma_parse(s1);
3207 break;
3208 default:
3209 if (tok == TOK_LINEFEED || tok == '!' || tok == TOK_CINT) {
3210 /* '!' is ignored to allow C scripts. numbers are ignored
3211 to emulate cpp behaviour */
3212 } else {
3213 if (!(saved_parse_flags & PARSE_FLAG_ASM_COMMENTS))
3214 warning("Ignoring unknown preprocessing directive #%s", get_tok_str(tok, &tokc));
3215 }
3216 break;
3217 }
3218 /* ignore other preprocess commands or #! for C scripts */
3219 while (tok != TOK_LINEFEED)
3220 next_nomacro();
3221 the_end:
3222 parse_flags = saved_parse_flags;
3223 }
3224
3225 /* evaluate escape codes in a string. */
parse_escape_string(CString * outstr,const uint8_t * buf,int is_long)3226 static void parse_escape_string(CString *outstr, const uint8_t *buf, int is_long)
3227 {
3228 int c, n;
3229 const uint8_t *p;
3230
3231 p = buf;
3232 for(;;) {
3233 c = *p;
3234 if (c == '\0')
3235 break;
3236 if (c == '\\') {
3237 p++;
3238 /* escape */
3239 c = *p;
3240 switch(c) {
3241 case '0': case '1': case '2': case '3':
3242 case '4': case '5': case '6': case '7':
3243 /* at most three octal digits */
3244 n = c - '0';
3245 p++;
3246 c = *p;
3247 if (isoct(c)) {
3248 n = n * 8 + c - '0';
3249 p++;
3250 c = *p;
3251 if (isoct(c)) {
3252 n = n * 8 + c - '0';
3253 p++;
3254 }
3255 }
3256 c = n;
3257 goto add_char_nonext;
3258 case 'x':
3259 case 'u':
3260 case 'U':
3261 p++;
3262 n = 0;
3263 for(;;) {
3264 c = *p;
3265 if (c >= 'a' && c <= 'f')
3266 c = c - 'a' + 10;
3267 else if (c >= 'A' && c <= 'F')
3268 c = c - 'A' + 10;
3269 else if (isnum(c))
3270 c = c - '0';
3271 else
3272 break;
3273 n = n * 16 + c;
3274 p++;
3275 }
3276 c = n;
3277 goto add_char_nonext;
3278 case 'a':
3279 c = '\a';
3280 break;
3281 case 'b':
3282 c = '\b';
3283 break;
3284 case 'f':
3285 c = '\f';
3286 break;
3287 case 'n':
3288 c = '\n';
3289 break;
3290 case 'r':
3291 c = '\r';
3292 break;
3293 case 't':
3294 c = '\t';
3295 break;
3296 case 'v':
3297 c = '\v';
3298 break;
3299 case 'e':
3300 if (!gnu_ext)
3301 goto invalid_escape;
3302 c = 27;
3303 break;
3304 case '\'':
3305 case '\"':
3306 case '\\':
3307 case '?':
3308 break;
3309 default:
3310 invalid_escape:
3311 if (c >= '!' && c <= '~')
3312 warning("unknown escape sequence: \'\\%c\'", c);
3313 else
3314 warning("unknown escape sequence: \'\\x%x\'", c);
3315 break;
3316 }
3317 }
3318 p++;
3319 add_char_nonext:
3320 if (!is_long)
3321 cstr_ccat(outstr, c);
3322 else
3323 cstr_wccat(outstr, c);
3324 }
3325 /* add a trailing '\0' */
3326 if (!is_long)
3327 cstr_ccat(outstr, '\0');
3328 else
3329 cstr_wccat(outstr, '\0');
3330 }
3331
3332 /* we use 64 bit numbers */
3333 #define BN_SIZE 2
3334
3335 /* bn = (bn << shift) | or_val */
bn_lshift(unsigned int * bn,int shift,int or_val)3336 void bn_lshift(unsigned int *bn, int shift, int or_val)
3337 {
3338 int i;
3339 unsigned int v;
3340 for(i=0;i<BN_SIZE;i++) {
3341 v = bn[i];
3342 bn[i] = (v << shift) | or_val;
3343 or_val = v >> (32 - shift);
3344 }
3345 }
3346
bn_zero(unsigned int * bn)3347 void bn_zero(unsigned int *bn)
3348 {
3349 int i;
3350 for(i=0;i<BN_SIZE;i++) {
3351 bn[i] = 0;
3352 }
3353 }
3354
3355 /* parse number in null terminated string 'p' and return it in the
3356 current token */
parse_number(const char * p)3357 void parse_number(const char *p)
3358 {
3359 int b, t, shift, frac_bits, s, exp_val, ch;
3360 char *q;
3361 unsigned int bn[BN_SIZE];
3362 double d;
3363
3364 /* number */
3365 q = token_buf;
3366 ch = *p++;
3367 t = ch;
3368 ch = *p++;
3369 *q++ = t;
3370 b = 10;
3371 if (t == '.') {
3372 goto float_frac_parse;
3373 } else if (t == '0') {
3374 if (ch == 'x' || ch == 'X') {
3375 q--;
3376 ch = *p++;
3377 b = 16;
3378 } else if (tcc_ext && (ch == 'b' || ch == 'B')) {
3379 q--;
3380 ch = *p++;
3381 b = 2;
3382 }
3383 }
3384 /* parse all digits. cannot check octal numbers at this stage
3385 because of floating point constants */
3386 while (1) {
3387 if (ch >= 'a' && ch <= 'f')
3388 t = ch - 'a' + 10;
3389 else if (ch >= 'A' && ch <= 'F')
3390 t = ch - 'A' + 10;
3391 else if (isnum(ch))
3392 t = ch - '0';
3393 else
3394 break;
3395 if (t >= b)
3396 break;
3397 if (q >= token_buf + STRING_MAX_SIZE) {
3398 num_too_long:
3399 error("number too long");
3400 }
3401 *q++ = ch;
3402 ch = *p++;
3403 }
3404 if (ch == '.' ||
3405 ((ch == 'e' || ch == 'E') && b == 10) ||
3406 ((ch == 'p' || ch == 'P') && (b == 16 || b == 2))) {
3407 if (b != 10) {
3408 /* NOTE: strtox should support that for hexa numbers, but
3409 non ISOC99 libcs do not support it, so we prefer to do
3410 it by hand */
3411 /* hexadecimal or binary floats */
3412 /* XXX: handle overflows */
3413 *q = '\0';
3414 if (b == 16)
3415 shift = 4;
3416 else
3417 shift = 2;
3418 bn_zero(bn);
3419 q = token_buf;
3420 while (1) {
3421 t = *q++;
3422 if (t == '\0') {
3423 break;
3424 } else if (t >= 'a') {
3425 t = t - 'a' + 10;
3426 } else if (t >= 'A') {
3427 t = t - 'A' + 10;
3428 } else {
3429 t = t - '0';
3430 }
3431 bn_lshift(bn, shift, t);
3432 }
3433 frac_bits = 0;
3434 if (ch == '.') {
3435 ch = *p++;
3436 while (1) {
3437 t = ch;
3438 if (t >= 'a' && t <= 'f') {
3439 t = t - 'a' + 10;
3440 } else if (t >= 'A' && t <= 'F') {
3441 t = t - 'A' + 10;
3442 } else if (t >= '0' && t <= '9') {
3443 t = t - '0';
3444 } else {
3445 break;
3446 }
3447 if (t >= b)
3448 error("invalid digit");
3449 bn_lshift(bn, shift, t);
3450 frac_bits += shift;
3451 ch = *p++;
3452 }
3453 }
3454 if (ch != 'p' && ch != 'P')
3455 expect("exponent");
3456 ch = *p++;
3457 s = 1;
3458 exp_val = 0;
3459 if (ch == '+') {
3460 ch = *p++;
3461 } else if (ch == '-') {
3462 s = -1;
3463 ch = *p++;
3464 }
3465 if (ch < '0' || ch > '9')
3466 expect("exponent digits");
3467 while (ch >= '0' && ch <= '9') {
3468 exp_val = exp_val * 10 + ch - '0';
3469 ch = *p++;
3470 }
3471 exp_val = exp_val * s;
3472
3473 /* now we can generate the number */
3474 /* XXX: should patch directly float number */
3475 d = (double)bn[1] * 4294967296.0 + (double)bn[0];
3476 d = ldexp(d, exp_val - frac_bits);
3477 t = toup(ch);
3478 if (t == 'F') {
3479 ch = *p++;
3480 tok = TOK_CFLOAT;
3481 /* float : should handle overflow */
3482 tokc.f = (float)d;
3483 } else if (t == 'L') {
3484 ch = *p++;
3485 tok = TOK_CLDOUBLE;
3486 /* XXX: not large enough */
3487 tokc.ld = (long double)d;
3488 } else {
3489 tok = TOK_CDOUBLE;
3490 tokc.d = d;
3491 }
3492 } else {
3493 /* decimal floats */
3494 if (ch == '.') {
3495 if (q >= token_buf + STRING_MAX_SIZE)
3496 goto num_too_long;
3497 *q++ = ch;
3498 ch = *p++;
3499 float_frac_parse:
3500 while (ch >= '0' && ch <= '9') {
3501 if (q >= token_buf + STRING_MAX_SIZE)
3502 goto num_too_long;
3503 *q++ = ch;
3504 ch = *p++;
3505 }
3506 }
3507 if (ch == 'e' || ch == 'E') {
3508 if (q >= token_buf + STRING_MAX_SIZE)
3509 goto num_too_long;
3510 *q++ = ch;
3511 ch = *p++;
3512 if (ch == '-' || ch == '+') {
3513 if (q >= token_buf + STRING_MAX_SIZE)
3514 goto num_too_long;
3515 *q++ = ch;
3516 ch = *p++;
3517 }
3518 if (ch < '0' || ch > '9')
3519 expect("exponent digits");
3520 while (ch >= '0' && ch <= '9') {
3521 if (q >= token_buf + STRING_MAX_SIZE)
3522 goto num_too_long;
3523 *q++ = ch;
3524 ch = *p++;
3525 }
3526 }
3527 *q = '\0';
3528 t = toup(ch);
3529 errno = 0;
3530 if (t == 'F') {
3531 ch = *p++;
3532 tok = TOK_CFLOAT;
3533 tokc.f = strtof(token_buf, NULL);
3534 } else if (t == 'L') {
3535 ch = *p++;
3536 tok = TOK_CLDOUBLE;
3537 tokc.ld = strtold(token_buf, NULL);
3538 } else {
3539 tok = TOK_CDOUBLE;
3540 tokc.d = strtod(token_buf, NULL);
3541 }
3542 }
3543 } else {
3544 unsigned long long n, n1;
3545 int lcount, ucount;
3546
3547 /* integer number */
3548 *q = '\0';
3549 q = token_buf;
3550 if (b == 10 && *q == '0') {
3551 b = 8;
3552 q++;
3553 }
3554 n = 0;
3555 while(1) {
3556 t = *q++;
3557 /* no need for checks except for base 10 / 8 errors */
3558 if (t == '\0') {
3559 break;
3560 } else if (t >= 'a') {
3561 t = t - 'a' + 10;
3562 } else if (t >= 'A') {
3563 t = t - 'A' + 10;
3564 } else {
3565 t = t - '0';
3566 if (t >= b)
3567 error("invalid digit");
3568 }
3569 n1 = n;
3570 n = n * b + t;
3571 /* detect overflow */
3572 /* XXX: this test is not reliable */
3573 if (n < n1)
3574 error("integer constant overflow");
3575 }
3576
3577 /* XXX: not exactly ANSI compliant */
3578 if ((n & 0xffffffff00000000LL) != 0) {
3579 if ((n >> 63) != 0)
3580 tok = TOK_CULLONG;
3581 else
3582 tok = TOK_CLLONG;
3583 } else if (n > 0x7fffffff) {
3584 tok = TOK_CUINT;
3585 } else {
3586 tok = TOK_CINT;
3587 }
3588 lcount = 0;
3589 ucount = 0;
3590 for(;;) {
3591 t = toup(ch);
3592 if (t == 'L') {
3593 if (lcount >= 2)
3594 error("three 'l's in integer constant");
3595 lcount++;
3596 if (lcount == 2) {
3597 if (tok == TOK_CINT)
3598 tok = TOK_CLLONG;
3599 else if (tok == TOK_CUINT)
3600 tok = TOK_CULLONG;
3601 }
3602 ch = *p++;
3603 } else if (t == 'U') {
3604 if (ucount >= 1)
3605 error("two 'u's in integer constant");
3606 ucount++;
3607 if (tok == TOK_CINT)
3608 tok = TOK_CUINT;
3609 else if (tok == TOK_CLLONG)
3610 tok = TOK_CULLONG;
3611 ch = *p++;
3612 } else {
3613 break;
3614 }
3615 }
3616 if (tok == TOK_CINT || tok == TOK_CUINT)
3617 tokc.ui = n;
3618 else
3619 tokc.ull = n;
3620 }
3621 }
3622
3623
3624 #define PARSE2(c1, tok1, c2, tok2) \
3625 case c1: \
3626 PEEKC(c, p); \
3627 if (c == c2) { \
3628 p++; \
3629 tok = tok2; \
3630 } else { \
3631 tok = tok1; \
3632 } \
3633 break;
3634
3635 /* return next token without macro substitution */
next_nomacro1(void)3636 static inline void next_nomacro1(void)
3637 {
3638 int t, c, is_long;
3639 TokenSym *ts;
3640 uint8_t *p, *p1;
3641 unsigned int h;
3642
3643 p = file->buf_ptr;
3644 redo_no_start:
3645 c = *p;
3646 switch(c) {
3647 case ' ':
3648 case '\t':
3649 case '\f':
3650 case '\v':
3651 case '\r':
3652 p++;
3653 goto redo_no_start;
3654
3655 case '\\':
3656 /* first look if it is in fact an end of buffer */
3657 if (p >= file->buf_end) {
3658 file->buf_ptr = p;
3659 handle_eob();
3660 p = file->buf_ptr;
3661 if (p >= file->buf_end)
3662 goto parse_eof;
3663 else
3664 goto redo_no_start;
3665 } else {
3666 file->buf_ptr = p;
3667 ch = *p;
3668 handle_stray();
3669 p = file->buf_ptr;
3670 goto redo_no_start;
3671 }
3672 parse_eof:
3673 {
3674 TCCState *s1 = tcc_state;
3675 if ((parse_flags & PARSE_FLAG_LINEFEED)
3676 && !(tok_flags & TOK_FLAG_EOF)) {
3677 tok_flags |= TOK_FLAG_EOF;
3678 tok = TOK_LINEFEED;
3679 goto keep_tok_flags;
3680 } else if (s1->include_stack_ptr == s1->include_stack ||
3681 !(parse_flags & PARSE_FLAG_PREPROCESS)) {
3682 /* no include left : end of file. */
3683 tok = TOK_EOF;
3684 } else {
3685 tok_flags &= ~TOK_FLAG_EOF;
3686 /* pop include file */
3687
3688 /* test if previous '#endif' was after a #ifdef at
3689 start of file */
3690 if (tok_flags & TOK_FLAG_ENDIF) {
3691 #ifdef INC_DEBUG
3692 printf("#endif %s\n", get_tok_str(file->ifndef_macro_saved, NULL));
3693 #endif
3694 add_cached_include(s1, file->inc_type, file->inc_filename,
3695 file->ifndef_macro_saved);
3696 }
3697
3698 /* add end of include file debug info */
3699 if (do_debug) {
3700 put_stabd(N_EINCL, 0, 0);
3701 }
3702 /* pop include stack */
3703 tcc_close(file);
3704 s1->include_stack_ptr--;
3705 file = *s1->include_stack_ptr;
3706 p = file->buf_ptr;
3707 goto redo_no_start;
3708 }
3709 }
3710 break;
3711
3712 case '\n':
3713 file->line_num++;
3714 tok_flags |= TOK_FLAG_BOL;
3715 p++;
3716 if (0 == (parse_flags & PARSE_FLAG_LINEFEED))
3717 goto redo_no_start;
3718 tok = TOK_LINEFEED;
3719 goto keep_tok_flags;
3720
3721 case '#':
3722 /* XXX: simplify */
3723 PEEKC(c, p);
3724 if ((tok_flags & TOK_FLAG_BOL) &&
3725 (parse_flags & PARSE_FLAG_PREPROCESS)) {
3726 file->buf_ptr = p;
3727 preprocess(tok_flags & TOK_FLAG_BOF);
3728 p = file->buf_ptr;
3729 goto redo_no_start;
3730 } else {
3731 if (c == '#') {
3732 p++;
3733 tok = TOK_TWOSHARPS;
3734 } else {
3735 if (parse_flags & PARSE_FLAG_ASM_COMMENTS) {
3736 p = parse_line_comment(p - 1);
3737 goto redo_no_start;
3738 } else {
3739 tok = '#';
3740 }
3741 }
3742 }
3743 break;
3744
3745 case 'a': case 'b': case 'c': case 'd':
3746 case 'e': case 'f': case 'g': case 'h':
3747 case 'i': case 'j': case 'k': case 'l':
3748 case 'm': case 'n': case 'o': case 'p':
3749 case 'q': case 'r': case 's': case 't':
3750 case 'u': case 'v': case 'w': case 'x':
3751 case 'y': case 'z':
3752 case 'A': case 'B': case 'C': case 'D':
3753 case 'E': case 'F': case 'G': case 'H':
3754 case 'I': case 'J': case 'K':
3755 case 'M': case 'N': case 'O': case 'P':
3756 case 'Q': case 'R': case 'S': case 'T':
3757 case 'U': case 'V': case 'W': case 'X':
3758 case 'Y': case 'Z':
3759 case '_':
3760 parse_ident_fast:
3761 p1 = p;
3762 h = TOK_HASH_INIT;
3763 h = TOK_HASH_FUNC(h, c);
3764 p++;
3765 for(;;) {
3766 c = *p;
3767 if (!isidnum_table[c])
3768 break;
3769 h = TOK_HASH_FUNC(h, c);
3770 p++;
3771 }
3772 if (c != '\\') {
3773 TokenSym **pts;
3774 int len;
3775
3776 /* fast case : no stray found, so we have the full token
3777 and we have already hashed it */
3778 len = p - p1;
3779 h &= (TOK_HASH_SIZE - 1);
3780 pts = &hash_ident[h];
3781 for(;;) {
3782 ts = *pts;
3783 if (!ts)
3784 break;
3785 if (ts->len == len && !memcmp(ts->str, p1, len))
3786 goto token_found;
3787 pts = &(ts->hash_next);
3788 }
3789 ts = tok_alloc_new(pts, p1, len);
3790 token_found: ;
3791 } else {
3792 /* slower case */
3793 cstr_reset(&tokcstr);
3794
3795 while (p1 < p) {
3796 cstr_ccat(&tokcstr, *p1);
3797 p1++;
3798 }
3799 p--;
3800 PEEKC(c, p);
3801 parse_ident_slow:
3802 while (isidnum_table[c]) {
3803 cstr_ccat(&tokcstr, c);
3804 PEEKC(c, p);
3805 }
3806 ts = tok_alloc(tokcstr.data, tokcstr.size);
3807 }
3808 tok = ts->tok;
3809 break;
3810 case 'L':
3811 t = p[1];
3812 if (t != '\\' && t != '\'' && t != '\"') {
3813 /* fast case */
3814 goto parse_ident_fast;
3815 } else {
3816 PEEKC(c, p);
3817 if (c == '\'' || c == '\"') {
3818 is_long = 1;
3819 goto str_const;
3820 } else {
3821 cstr_reset(&tokcstr);
3822 cstr_ccat(&tokcstr, 'L');
3823 goto parse_ident_slow;
3824 }
3825 }
3826 break;
3827 case '0': case '1': case '2': case '3':
3828 case '4': case '5': case '6': case '7':
3829 case '8': case '9':
3830
3831 cstr_reset(&tokcstr);
3832 /* after the first digit, accept digits, alpha, '.' or sign if
3833 prefixed by 'eEpP' */
3834 parse_num:
3835 for(;;) {
3836 t = c;
3837 cstr_ccat(&tokcstr, c);
3838 PEEKC(c, p);
3839 if (!(isnum(c) || isid(c) || c == '.' ||
3840 ((c == '+' || c == '-') &&
3841 (t == 'e' || t == 'E' || t == 'p' || t == 'P'))))
3842 break;
3843 }
3844 /* We add a trailing '\0' to ease parsing */
3845 cstr_ccat(&tokcstr, '\0');
3846 tokc.cstr = &tokcstr;
3847 tok = TOK_PPNUM;
3848 break;
3849 case '.':
3850 /* special dot handling because it can also start a number */
3851 PEEKC(c, p);
3852 if (isnum(c)) {
3853 cstr_reset(&tokcstr);
3854 cstr_ccat(&tokcstr, '.');
3855 goto parse_num;
3856 } else if (c == '.') {
3857 PEEKC(c, p);
3858 if (c != '.')
3859 expect("'.'");
3860 PEEKC(c, p);
3861 tok = TOK_DOTS;
3862 } else {
3863 tok = '.';
3864 }
3865 break;
3866 case '\'':
3867 case '\"':
3868 is_long = 0;
3869 str_const:
3870 {
3871 CString str;
3872 int sep;
3873
3874 sep = c;
3875
3876 /* parse the string */
3877 cstr_new(&str);
3878 p = parse_pp_string(p, sep, &str);
3879 cstr_ccat(&str, '\0');
3880
3881 /* eval the escape (should be done as TOK_PPNUM) */
3882 cstr_reset(&tokcstr);
3883 parse_escape_string(&tokcstr, str.data, is_long);
3884 cstr_free(&str);
3885
3886 if (sep == '\'') {
3887 int char_size;
3888 /* XXX: make it portable */
3889 if (!is_long)
3890 char_size = 1;
3891 else
3892 char_size = sizeof(nwchar_t);
3893 if (tokcstr.size <= char_size)
3894 error("empty character constant");
3895 if (tokcstr.size > 2 * char_size)
3896 warning("multi-character character constant");
3897 if (!is_long) {
3898 tokc.i = *(int8_t *)tokcstr.data;
3899 tok = TOK_CCHAR;
3900 } else {
3901 tokc.i = *(nwchar_t *)tokcstr.data;
3902 tok = TOK_LCHAR;
3903 }
3904 } else {
3905 tokc.cstr = &tokcstr;
3906 if (!is_long)
3907 tok = TOK_STR;
3908 else
3909 tok = TOK_LSTR;
3910 }
3911 }
3912 break;
3913
3914 case '<':
3915 PEEKC(c, p);
3916 if (c == '=') {
3917 p++;
3918 tok = TOK_LE;
3919 } else if (c == '<') {
3920 PEEKC(c, p);
3921 if (c == '=') {
3922 p++;
3923 tok = TOK_A_SHL;
3924 } else {
3925 tok = TOK_SHL;
3926 }
3927 } else {
3928 tok = TOK_LT;
3929 }
3930 break;
3931
3932 case '>':
3933 PEEKC(c, p);
3934 if (c == '=') {
3935 p++;
3936 tok = TOK_GE;
3937 } else if (c == '>') {
3938 PEEKC(c, p);
3939 if (c == '=') {
3940 p++;
3941 tok = TOK_A_SAR;
3942 } else {
3943 tok = TOK_SAR;
3944 }
3945 } else {
3946 tok = TOK_GT;
3947 }
3948 break;
3949
3950 case '&':
3951 PEEKC(c, p);
3952 if (c == '&') {
3953 p++;
3954 tok = TOK_LAND;
3955 } else if (c == '=') {
3956 p++;
3957 tok = TOK_A_AND;
3958 } else {
3959 tok = '&';
3960 }
3961 break;
3962
3963 case '|':
3964 PEEKC(c, p);
3965 if (c == '|') {
3966 p++;
3967 tok = TOK_LOR;
3968 } else if (c == '=') {
3969 p++;
3970 tok = TOK_A_OR;
3971 } else {
3972 tok = '|';
3973 }
3974 break;
3975
3976 case '+':
3977 PEEKC(c, p);
3978 if (c == '+') {
3979 p++;
3980 tok = TOK_INC;
3981 } else if (c == '=') {
3982 p++;
3983 tok = TOK_A_ADD;
3984 } else {
3985 tok = '+';
3986 }
3987 break;
3988
3989 case '-':
3990 PEEKC(c, p);
3991 if (c == '-') {
3992 p++;
3993 tok = TOK_DEC;
3994 } else if (c == '=') {
3995 p++;
3996 tok = TOK_A_SUB;
3997 } else if (c == '>') {
3998 p++;
3999 tok = TOK_ARROW;
4000 } else {
4001 tok = '-';
4002 }
4003 break;
4004
4005 PARSE2('!', '!', '=', TOK_NE)
4006 PARSE2('=', '=', '=', TOK_EQ)
4007 PARSE2('*', '*', '=', TOK_A_MUL)
4008 PARSE2('%', '%', '=', TOK_A_MOD)
4009 PARSE2('^', '^', '=', TOK_A_XOR)
4010
4011 /* comments or operator */
4012 case '/':
4013 PEEKC(c, p);
4014 if (c == '*') {
4015 p = parse_comment(p);
4016 goto redo_no_start;
4017 } else if (c == '/') {
4018 p = parse_line_comment(p);
4019 goto redo_no_start;
4020 } else if (c == '=') {
4021 p++;
4022 tok = TOK_A_DIV;
4023 } else {
4024 tok = '/';
4025 }
4026 break;
4027
4028 /* simple tokens */
4029 case '(':
4030 case ')':
4031 case '[':
4032 case ']':
4033 case '{':
4034 case '}':
4035 case ',':
4036 case ';':
4037 case ':':
4038 case '?':
4039 case '~':
4040 case '$': /* only used in assembler */
4041 case '@': /* dito */
4042 tok = c;
4043 p++;
4044 break;
4045 default:
4046 error("unrecognized character \\x%02x", c);
4047 break;
4048 }
4049 tok_flags = 0;
4050 keep_tok_flags:
4051 file->buf_ptr = p;
4052 #if defined(PARSE_DEBUG)
4053 printf("token = %s\n", get_tok_str(tok, &tokc));
4054 #endif
4055 }
4056
4057 /* return next token without macro substitution. Can read input from
4058 macro_ptr buffer */
next_nomacro(void)4059 static void next_nomacro(void)
4060 {
4061 if (macro_ptr) {
4062 redo:
4063 tok = *macro_ptr;
4064 if (tok) {
4065 TOK_GET(tok, macro_ptr, tokc);
4066 if (tok == TOK_LINENUM) {
4067 file->line_num = tokc.i;
4068 goto redo;
4069 }
4070 }
4071 } else {
4072 next_nomacro1();
4073 }
4074 }
4075
4076 /* substitute args in macro_str and return allocated string */
macro_arg_subst(Sym ** nested_list,int * macro_str,Sym * args)4077 static int *macro_arg_subst(Sym **nested_list, int *macro_str, Sym *args)
4078 {
4079 int *st, last_tok, t, notfirst;
4080 Sym *s;
4081 CValue cval;
4082 TokenString str;
4083 CString cstr;
4084
4085 tok_str_new(&str);
4086 last_tok = 0;
4087 while(1) {
4088 TOK_GET(t, macro_str, cval);
4089 if (!t)
4090 break;
4091 if (t == '#') {
4092 /* stringize */
4093 TOK_GET(t, macro_str, cval);
4094 if (!t)
4095 break;
4096 s = sym_find2(args, t);
4097 if (s) {
4098 cstr_new(&cstr);
4099 st = (int *)s->c;
4100 notfirst = 0;
4101 while (*st) {
4102 if (notfirst)
4103 cstr_ccat(&cstr, ' ');
4104 TOK_GET(t, st, cval);
4105 cstr_cat(&cstr, get_tok_str(t, &cval));
4106 #ifndef PP_NOSPACES
4107 notfirst = 1;
4108 #endif
4109 }
4110 cstr_ccat(&cstr, '\0');
4111 #ifdef PP_DEBUG
4112 printf("stringize: %s\n", (char *)cstr.data);
4113 #endif
4114 /* add string */
4115 cval.cstr = &cstr;
4116 tok_str_add2(&str, TOK_STR, &cval);
4117 cstr_free(&cstr);
4118 } else {
4119 tok_str_add2(&str, t, &cval);
4120 }
4121 } else if (t >= TOK_IDENT) {
4122 s = sym_find2(args, t);
4123 if (s) {
4124 st = (int *)s->c;
4125 /* if '##' is present before or after, no arg substitution */
4126 if (*macro_str == TOK_TWOSHARPS || last_tok == TOK_TWOSHARPS) {
4127 /* special case for var arg macros : ## eats the
4128 ',' if empty VA_ARGS variable. */
4129 /* XXX: test of the ',' is not 100%
4130 reliable. should fix it to avoid security
4131 problems */
4132 if (gnu_ext && s->type.t &&
4133 last_tok == TOK_TWOSHARPS &&
4134 str.len >= 2 && str.str[str.len - 2] == ',') {
4135 if (*st == 0) {
4136 /* suppress ',' '##' */
4137 str.len -= 2;
4138 } else {
4139 /* suppress '##' and add variable */
4140 str.len--;
4141 goto add_var;
4142 }
4143 } else {
4144 int t1;
4145 add_var:
4146 for(;;) {
4147 TOK_GET(t1, st, cval);
4148 if (!t1)
4149 break;
4150 tok_str_add2(&str, t1, &cval);
4151 }
4152 }
4153 } else {
4154 /* NOTE: the stream cannot be read when macro
4155 substituing an argument */
4156 macro_subst(&str, nested_list, st, NULL);
4157 }
4158 } else {
4159 tok_str_add(&str, t);
4160 }
4161 } else {
4162 tok_str_add2(&str, t, &cval);
4163 }
4164 last_tok = t;
4165 }
4166 tok_str_add(&str, 0);
4167 return str.str;
4168 }
4169
4170 static char const ab_month_name[12][4] =
4171 {
4172 "Jan", "Feb", "Mar", "Apr", "May", "Jun",
4173 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
4174 };
4175
4176 /* do macro substitution of current token with macro 's' and add
4177 result to (tok_str,tok_len). 'nested_list' is the list of all
4178 macros we got inside to avoid recursing. Return non zero if no
4179 substitution needs to be done */
macro_subst_tok(TokenString * tok_str,Sym ** nested_list,Sym * s,struct macro_level ** can_read_stream)4180 static int macro_subst_tok(TokenString *tok_str,
4181 Sym **nested_list, Sym *s, struct macro_level **can_read_stream)
4182 {
4183 Sym *args, *sa, *sa1;
4184 int mstr_allocated, parlevel, *mstr, t, t1;
4185 TokenString str;
4186 char *cstrval;
4187 CValue cval;
4188 CString cstr;
4189 char buf[32];
4190
4191 /* if symbol is a macro, prepare substitution */
4192 /* special macros */
4193 if (tok == TOK___LINE__) {
4194 snprintf(buf, sizeof(buf), "%d", file->line_num);
4195 cstrval = buf;
4196 t1 = TOK_PPNUM;
4197 goto add_cstr1;
4198 } else if (tok == TOK___FILE__) {
4199 cstrval = file->filename;
4200 goto add_cstr;
4201 } else if (tok == TOK___DATE__ || tok == TOK___TIME__) {
4202 time_t ti;
4203 struct tm *tm;
4204
4205 time(&ti);
4206 tm = localtime(&ti);
4207 if (tok == TOK___DATE__) {
4208 snprintf(buf, sizeof(buf), "%s %2d %d",
4209 ab_month_name[tm->tm_mon], tm->tm_mday, tm->tm_year + 1900);
4210 } else {
4211 snprintf(buf, sizeof(buf), "%02d:%02d:%02d",
4212 tm->tm_hour, tm->tm_min, tm->tm_sec);
4213 }
4214 cstrval = buf;
4215 add_cstr:
4216 t1 = TOK_STR;
4217 add_cstr1:
4218 cstr_new(&cstr);
4219 cstr_cat(&cstr, cstrval);
4220 cstr_ccat(&cstr, '\0');
4221 cval.cstr = &cstr;
4222 tok_str_add2(tok_str, t1, &cval);
4223 cstr_free(&cstr);
4224 } else {
4225 mstr = (int *)s->c;
4226 mstr_allocated = 0;
4227 if (s->type.t == MACRO_FUNC) {
4228 /* NOTE: we do not use next_nomacro to avoid eating the
4229 next token. XXX: find better solution */
4230 redo:
4231 if (macro_ptr) {
4232 t = *macro_ptr;
4233 if (t == 0 && can_read_stream) {
4234 /* end of macro stream: we must look at the token
4235 after in the file */
4236 struct macro_level *ml = *can_read_stream;
4237 macro_ptr = NULL;
4238 if (ml)
4239 {
4240 macro_ptr = ml->p;
4241 ml->p = NULL;
4242 *can_read_stream = ml -> prev;
4243 }
4244 goto redo;
4245 }
4246 } else {
4247 /* XXX: incorrect with comments */
4248 ch = file->buf_ptr[0];
4249 while (is_space(ch) || ch == '\n')
4250 cinp();
4251 t = ch;
4252 }
4253 if (t != '(') /* no macro subst */
4254 return -1;
4255
4256 /* argument macro */
4257 next_nomacro();
4258 next_nomacro();
4259 args = NULL;
4260 sa = s->next;
4261 /* NOTE: empty args are allowed, except if no args */
4262 for(;;) {
4263 /* handle '()' case */
4264 if (!args && !sa && tok == ')')
4265 break;
4266 if (!sa)
4267 error("macro '%s' used with too many args",
4268 get_tok_str(s->v, 0));
4269 tok_str_new(&str);
4270 parlevel = 0;
4271 /* NOTE: non zero sa->t indicates VA_ARGS */
4272 while ((parlevel > 0 ||
4273 (tok != ')' &&
4274 (tok != ',' || sa->type.t))) &&
4275 tok != -1) {
4276 if (tok == '(')
4277 parlevel++;
4278 else if (tok == ')')
4279 parlevel--;
4280 if (tok != TOK_LINEFEED)
4281 tok_str_add2(&str, tok, &tokc);
4282 next_nomacro();
4283 }
4284 tok_str_add(&str, 0);
4285 sym_push2(&args, sa->v & ~SYM_FIELD, sa->type.t, (int)str.str);
4286 sa = sa->next;
4287 if (tok == ')') {
4288 /* special case for gcc var args: add an empty
4289 var arg argument if it is omitted */
4290 if (sa && sa->type.t && gnu_ext)
4291 continue;
4292 else
4293 break;
4294 }
4295 if (tok != ',')
4296 expect(",");
4297 next_nomacro();
4298 }
4299 if (sa) {
4300 error("macro '%s' used with too few args",
4301 get_tok_str(s->v, 0));
4302 }
4303
4304 /* now subst each arg */
4305 mstr = macro_arg_subst(nested_list, mstr, args);
4306 /* free memory */
4307 sa = args;
4308 while (sa) {
4309 sa1 = sa->prev;
4310 tok_str_free((int *)sa->c);
4311 sym_free(sa);
4312 sa = sa1;
4313 }
4314 mstr_allocated = 1;
4315 }
4316 sym_push2(nested_list, s->v, 0, 0);
4317 macro_subst(tok_str, nested_list, mstr, can_read_stream);
4318 /* pop nested defined symbol */
4319 sa1 = *nested_list;
4320 *nested_list = sa1->prev;
4321 sym_free(sa1);
4322 if (mstr_allocated)
4323 tok_str_free(mstr);
4324 }
4325 return 0;
4326 }
4327
4328 /* handle the '##' operator. Return NULL if no '##' seen. Otherwise
4329 return the resulting string (which must be freed). */
macro_twosharps(const int * macro_str)4330 static inline int *macro_twosharps(const int *macro_str)
4331 {
4332 TokenSym *ts;
4333 const int *macro_ptr1, *start_macro_ptr, *ptr, *saved_macro_ptr;
4334 int t;
4335 const char *p1, *p2;
4336 CValue cval;
4337 TokenString macro_str1;
4338 CString cstr;
4339
4340 start_macro_ptr = macro_str;
4341 /* we search the first '##' */
4342 for(;;) {
4343 macro_ptr1 = macro_str;
4344 TOK_GET(t, macro_str, cval);
4345 /* nothing more to do if end of string */
4346 if (t == 0)
4347 return NULL;
4348 if (*macro_str == TOK_TWOSHARPS)
4349 break;
4350 }
4351
4352 /* we saw '##', so we need more processing to handle it */
4353 cstr_new(&cstr);
4354 tok_str_new(¯o_str1);
4355 tok = t;
4356 tokc = cval;
4357
4358 /* add all tokens seen so far */
4359 for(ptr = start_macro_ptr; ptr < macro_ptr1;) {
4360 TOK_GET(t, ptr, cval);
4361 tok_str_add2(¯o_str1, t, &cval);
4362 }
4363 saved_macro_ptr = macro_ptr;
4364 /* XXX: get rid of the use of macro_ptr here */
4365 macro_ptr = (int *)macro_str;
4366 for(;;) {
4367 while (*macro_ptr == TOK_TWOSHARPS) {
4368 macro_ptr++;
4369 macro_ptr1 = macro_ptr;
4370 t = *macro_ptr;
4371 if (t) {
4372 TOK_GET(t, macro_ptr, cval);
4373 /* We concatenate the two tokens if we have an
4374 identifier or a preprocessing number */
4375 cstr_reset(&cstr);
4376 p1 = get_tok_str(tok, &tokc);
4377 cstr_cat(&cstr, p1);
4378 p2 = get_tok_str(t, &cval);
4379 cstr_cat(&cstr, p2);
4380 cstr_ccat(&cstr, '\0');
4381
4382 if ((tok >= TOK_IDENT || tok == TOK_PPNUM) &&
4383 (t >= TOK_IDENT || t == TOK_PPNUM)) {
4384 if (tok == TOK_PPNUM) {
4385 /* if number, then create a number token */
4386 /* NOTE: no need to allocate because
4387 tok_str_add2() does it */
4388 cstr_reset(&tokcstr);
4389 tokcstr = cstr;
4390 cstr_new(&cstr);
4391 tokc.cstr = &tokcstr;
4392 } else {
4393 /* if identifier, we must do a test to
4394 validate we have a correct identifier */
4395 if (t == TOK_PPNUM) {
4396 const char *p;
4397 int c;
4398
4399 p = p2;
4400 for(;;) {
4401 c = *p;
4402 if (c == '\0')
4403 break;
4404 p++;
4405 if (!isnum(c) && !isid(c))
4406 goto error_pasting;
4407 }
4408 }
4409 ts = tok_alloc(cstr.data, strlen(cstr.data));
4410 tok = ts->tok; /* modify current token */
4411 }
4412 } else {
4413 const char *str = cstr.data;
4414 const unsigned char *q;
4415
4416 /* we look for a valid token */
4417 /* XXX: do more extensive checks */
4418 if (!strcmp(str, ">>=")) {
4419 tok = TOK_A_SAR;
4420 } else if (!strcmp(str, "<<=")) {
4421 tok = TOK_A_SHL;
4422 } else if (strlen(str) == 2) {
4423 /* search in two bytes table */
4424 q = tok_two_chars;
4425 for(;;) {
4426 if (!*q)
4427 goto error_pasting;
4428 if (q[0] == str[0] && q[1] == str[1])
4429 break;
4430 q += 3;
4431 }
4432 tok = q[2];
4433 } else {
4434 error_pasting:
4435 /* NOTE: because get_tok_str use a static buffer,
4436 we must save it */
4437 cstr_reset(&cstr);
4438 p1 = get_tok_str(tok, &tokc);
4439 cstr_cat(&cstr, p1);
4440 cstr_ccat(&cstr, '\0');
4441 p2 = get_tok_str(t, &cval);
4442 warning("pasting \"%s\" and \"%s\" does not give a valid preprocessing token", cstr.data, p2);
4443 /* cannot merge tokens: just add them separately */
4444 tok_str_add2(¯o_str1, tok, &tokc);
4445 /* XXX: free associated memory ? */
4446 tok = t;
4447 tokc = cval;
4448 }
4449 }
4450 }
4451 }
4452 tok_str_add2(¯o_str1, tok, &tokc);
4453 next_nomacro();
4454 if (tok == 0)
4455 break;
4456 }
4457 macro_ptr = (int *)saved_macro_ptr;
4458 cstr_free(&cstr);
4459 tok_str_add(¯o_str1, 0);
4460 return macro_str1.str;
4461 }
4462
4463
4464 /* do macro substitution of macro_str and add result to
4465 (tok_str,tok_len). 'nested_list' is the list of all macros we got
4466 inside to avoid recursing. */
macro_subst(TokenString * tok_str,Sym ** nested_list,const int * macro_str,struct macro_level ** can_read_stream)4467 static void macro_subst(TokenString *tok_str, Sym **nested_list,
4468 const int *macro_str, struct macro_level ** can_read_stream)
4469 {
4470 Sym *s;
4471 int *macro_str1;
4472 const int *ptr;
4473 int t, ret;
4474 CValue cval;
4475 struct macro_level ml;
4476
4477 /* first scan for '##' operator handling */
4478 ptr = macro_str;
4479 macro_str1 = macro_twosharps(ptr);
4480 if (macro_str1)
4481 ptr = macro_str1;
4482 while (1) {
4483 /* NOTE: ptr == NULL can only happen if tokens are read from
4484 file stream due to a macro function call */
4485 if (ptr == NULL)
4486 break;
4487 TOK_GET(t, ptr, cval);
4488 if (t == 0)
4489 break;
4490 s = define_find(t);
4491 if (s != NULL) {
4492 /* if nested substitution, do nothing */
4493 if (sym_find2(*nested_list, t))
4494 goto no_subst;
4495 ml.p = macro_ptr;
4496 if (can_read_stream)
4497 ml.prev = *can_read_stream, *can_read_stream = &ml;
4498 macro_ptr = (int *)ptr;
4499 tok = t;
4500 ret = macro_subst_tok(tok_str, nested_list, s, can_read_stream);
4501 ptr = (int *)macro_ptr;
4502 macro_ptr = ml.p;
4503 if (can_read_stream && *can_read_stream == &ml)
4504 *can_read_stream = ml.prev;
4505 if (ret != 0)
4506 goto no_subst;
4507 } else {
4508 no_subst:
4509 tok_str_add2(tok_str, t, &cval);
4510 }
4511 }
4512 if (macro_str1)
4513 tok_str_free(macro_str1);
4514 }
4515
4516 /* return next token with macro substitution */
next(void)4517 static void next(void)
4518 {
4519 Sym *nested_list, *s;
4520 TokenString str;
4521 struct macro_level *ml;
4522
4523 redo:
4524 next_nomacro();
4525 if (!macro_ptr) {
4526 /* if not reading from macro substituted string, then try
4527 to substitute macros */
4528 if (tok >= TOK_IDENT &&
4529 (parse_flags & PARSE_FLAG_PREPROCESS)) {
4530 s = define_find(tok);
4531 if (s) {
4532 /* we have a macro: we try to substitute */
4533 tok_str_new(&str);
4534 nested_list = NULL;
4535 ml = NULL;
4536 if (macro_subst_tok(&str, &nested_list, s, &ml) == 0) {
4537 /* substitution done, NOTE: maybe empty */
4538 tok_str_add(&str, 0);
4539 macro_ptr = str.str;
4540 macro_ptr_allocated = str.str;
4541 goto redo;
4542 }
4543 }
4544 }
4545 } else {
4546 if (tok == 0) {
4547 /* end of macro or end of unget buffer */
4548 if (unget_buffer_enabled) {
4549 macro_ptr = unget_saved_macro_ptr;
4550 unget_buffer_enabled = 0;
4551 } else {
4552 /* end of macro string: free it */
4553 tok_str_free(macro_ptr_allocated);
4554 macro_ptr = NULL;
4555 }
4556 goto redo;
4557 }
4558 }
4559
4560 /* convert preprocessor tokens into C tokens */
4561 if (tok == TOK_PPNUM &&
4562 (parse_flags & PARSE_FLAG_TOK_NUM)) {
4563 parse_number((char *)tokc.cstr->data);
4564 }
4565 }
4566
4567 /* push back current token and set current token to 'last_tok'. Only
4568 identifier case handled for labels. */
unget_tok(int last_tok)4569 static inline void unget_tok(int last_tok)
4570 {
4571 int i, n;
4572 int *q;
4573 unget_saved_macro_ptr = macro_ptr;
4574 unget_buffer_enabled = 1;
4575 q = unget_saved_buffer;
4576 macro_ptr = q;
4577 *q++ = tok;
4578 n = tok_ext_size(tok) - 1;
4579 for(i=0;i<n;i++)
4580 *q++ = tokc.tab[i];
4581 *q = 0; /* end of token string */
4582 tok = last_tok;
4583 }
4584
4585
swap(int * p,int * q)4586 void swap(int *p, int *q)
4587 {
4588 int t;
4589 t = *p;
4590 *p = *q;
4591 *q = t;
4592 }
4593
vsetc(CType * type,int r,CValue * vc)4594 void vsetc(CType *type, int r, CValue *vc)
4595 {
4596 int v;
4597
4598 if (vtop >= vstack + (VSTACK_SIZE - 1))
4599 error("memory full");
4600 /* cannot let cpu flags if other instruction are generated. Also
4601 avoid leaving VT_JMP anywhere except on the top of the stack
4602 because it would complicate the code generator. */
4603 if (vtop >= vstack) {
4604 v = vtop->r & VT_VALMASK;
4605 if (v == VT_CMP || (v & ~1) == VT_JMP)
4606 gv(RC_INT);
4607 }
4608 vtop++;
4609 vtop->type = *type;
4610 vtop->r = r;
4611 vtop->r2 = VT_CONST;
4612 vtop->c = *vc;
4613 }
4614
4615 /* push integer constant */
vpushi(int v)4616 void vpushi(int v)
4617 {
4618 CValue cval;
4619 cval.i = v;
4620 vsetc(&int_type, VT_CONST, &cval);
4621 }
4622
4623 /* Return a static symbol pointing to a section */
get_sym_ref(CType * type,Section * sec,unsigned long offset,unsigned long size)4624 static Sym *get_sym_ref(CType *type, Section *sec,
4625 unsigned long offset, unsigned long size)
4626 {
4627 int v;
4628 Sym *sym;
4629
4630 v = anon_sym++;
4631 sym = global_identifier_push(v, type->t | VT_STATIC, 0);
4632 sym->type.ref = type->ref;
4633 sym->r = VT_CONST | VT_SYM;
4634 put_extern_sym(sym, sec, offset, size);
4635 return sym;
4636 }
4637
4638 /* push a reference to a section offset by adding a dummy symbol */
vpush_ref(CType * type,Section * sec,unsigned long offset,unsigned long size)4639 static void vpush_ref(CType *type, Section *sec, unsigned long offset, unsigned long size)
4640 {
4641 CValue cval;
4642
4643 cval.ul = 0;
4644 vsetc(type, VT_CONST | VT_SYM, &cval);
4645 vtop->sym = get_sym_ref(type, sec, offset, size);
4646 }
4647
4648 /* define a new external reference to a symbol 'v' of type 'u' */
external_global_sym(int v,CType * type,int r)4649 static Sym *external_global_sym(int v, CType *type, int r)
4650 {
4651 Sym *s;
4652
4653 s = sym_find(v);
4654 if (!s) {
4655 /* push forward reference */
4656 s = global_identifier_push(v, type->t | VT_EXTERN, 0);
4657 s->type.ref = type->ref;
4658 s->r = r | VT_CONST | VT_SYM;
4659 }
4660 return s;
4661 }
4662
4663 /* define a new external reference to a symbol 'v' of type 'u' */
external_sym(int v,CType * type,int r)4664 static Sym *external_sym(int v, CType *type, int r)
4665 {
4666 Sym *s;
4667
4668 s = sym_find(v);
4669 if (!s) {
4670 /* push forward reference */
4671 s = sym_push(v, type, r | VT_CONST | VT_SYM, 0);
4672 s->type.t |= VT_EXTERN;
4673 } else {
4674 if (!is_compatible_types(&s->type, type))
4675 error("incompatible types for redefinition of '%s'",
4676 get_tok_str(v, NULL));
4677 }
4678 return s;
4679 }
4680
4681 /* push a reference to global symbol v */
vpush_global_sym(CType * type,int v)4682 static void vpush_global_sym(CType *type, int v)
4683 {
4684 Sym *sym;
4685 CValue cval;
4686
4687 sym = external_global_sym(v, type, 0);
4688 cval.ul = 0;
4689 vsetc(type, VT_CONST | VT_SYM, &cval);
4690 vtop->sym = sym;
4691 }
4692
vset(CType * type,int r,int v)4693 void vset(CType *type, int r, int v)
4694 {
4695 CValue cval;
4696
4697 cval.i = v;
4698 vsetc(type, r, &cval);
4699 }
4700
vseti(int r,int v)4701 void vseti(int r, int v)
4702 {
4703 CType type;
4704 type.t = VT_INT;
4705 vset(&type, r, v);
4706 }
4707
vswap(void)4708 void vswap(void)
4709 {
4710 SValue tmp;
4711
4712 tmp = vtop[0];
4713 vtop[0] = vtop[-1];
4714 vtop[-1] = tmp;
4715 }
4716
vpushv(SValue * v)4717 void vpushv(SValue *v)
4718 {
4719 if (vtop >= vstack + (VSTACK_SIZE - 1))
4720 error("memory full");
4721 vtop++;
4722 *vtop = *v;
4723 }
4724
vdup(void)4725 void vdup(void)
4726 {
4727 vpushv(vtop);
4728 }
4729
4730 /* save r to the memory stack, and mark it as being free */
save_reg(int r)4731 void save_reg(int r)
4732 {
4733 int l, saved, size, align;
4734 SValue *p, sv;
4735 CType *type;
4736
4737 /* modify all stack values */
4738 saved = 0;
4739 l = 0;
4740 for(p=vstack;p<=vtop;p++) {
4741 if ((p->r & VT_VALMASK) == r ||
4742 ((p->type.t & VT_BTYPE) == VT_LLONG && (p->r2 & VT_VALMASK) == r)) {
4743 /* must save value on stack if not already done */
4744 if (!saved) {
4745 /* NOTE: must reload 'r' because r might be equal to r2 */
4746 r = p->r & VT_VALMASK;
4747 /* store register in the stack */
4748 type = &p->type;
4749 if ((p->r & VT_LVAL) ||
4750 (!is_float(type->t) && (type->t & VT_BTYPE) != VT_LLONG))
4751 type = &int_type;
4752 size = type_size(type, &align);
4753 loc = (loc - size) & -align;
4754 sv.type.t = type->t;
4755 sv.r = VT_LOCAL | VT_LVAL;
4756 sv.c.ul = loc;
4757 store(r, &sv);
4758 #ifdef TCC_TARGET_I386
4759 /* x86 specific: need to pop fp register ST0 if saved */
4760 if (r == TREG_ST0) {
4761 o(0xd9dd); /* fstp %st(1) */
4762 }
4763 #endif
4764 /* special long long case */
4765 if ((type->t & VT_BTYPE) == VT_LLONG) {
4766 sv.c.ul += 4;
4767 store(p->r2, &sv);
4768 }
4769 l = loc;
4770 saved = 1;
4771 }
4772 /* mark that stack entry as being saved on the stack */
4773 if (p->r & VT_LVAL) {
4774 /* also clear the bounded flag because the
4775 relocation address of the function was stored in
4776 p->c.ul */
4777 p->r = (p->r & ~(VT_VALMASK | VT_BOUNDED)) | VT_LLOCAL;
4778 } else {
4779 p->r = lvalue_type(p->type.t) | VT_LOCAL;
4780 }
4781 p->r2 = VT_CONST;
4782 p->c.ul = l;
4783 }
4784 }
4785 }
4786
4787 /* find a register of class 'rc2' with at most one reference on stack.
4788 * If none, call get_reg(rc) */
get_reg_ex(int rc,int rc2)4789 int get_reg_ex(int rc, int rc2)
4790 {
4791 int r;
4792 SValue *p;
4793
4794 for(r=0;r<NB_REGS;r++) {
4795 if (reg_classes[r] & rc2) {
4796 int n;
4797 n=0;
4798 for(p = vstack; p <= vtop; p++) {
4799 if ((p->r & VT_VALMASK) == r ||
4800 (p->r2 & VT_VALMASK) == r)
4801 n++;
4802 }
4803 if (n <= 1)
4804 return r;
4805 }
4806 }
4807 return get_reg(rc);
4808 }
4809
4810 /* find a free register of class 'rc'. If none, save one register */
get_reg(int rc)4811 int get_reg(int rc)
4812 {
4813 int r;
4814 SValue *p;
4815
4816 /* find a free register */
4817 for(r=0;r<NB_REGS;r++) {
4818 if (reg_classes[r] & rc) {
4819 for(p=vstack;p<=vtop;p++) {
4820 if ((p->r & VT_VALMASK) == r ||
4821 (p->r2 & VT_VALMASK) == r)
4822 goto notfound;
4823 }
4824 return r;
4825 }
4826 notfound: ;
4827 }
4828
4829 /* no register left : free the first one on the stack (VERY
4830 IMPORTANT to start from the bottom to ensure that we don't
4831 spill registers used in gen_opi()) */
4832 for(p=vstack;p<=vtop;p++) {
4833 r = p->r & VT_VALMASK;
4834 if (r < VT_CONST && (reg_classes[r] & rc))
4835 goto save_found;
4836 /* also look at second register (if long long) */
4837 r = p->r2 & VT_VALMASK;
4838 if (r < VT_CONST && (reg_classes[r] & rc)) {
4839 save_found:
4840 save_reg(r);
4841 return r;
4842 }
4843 }
4844 /* Should never comes here */
4845 return -1;
4846 }
4847
4848 /* save registers up to (vtop - n) stack entry */
save_regs(int n)4849 void save_regs(int n)
4850 {
4851 int r;
4852 SValue *p, *p1;
4853 p1 = vtop - n;
4854 for(p = vstack;p <= p1; p++) {
4855 r = p->r & VT_VALMASK;
4856 if (r < VT_CONST) {
4857 save_reg(r);
4858 }
4859 }
4860 }
4861
4862 /* move register 's' to 'r', and flush previous value of r to memory
4863 if needed */
move_reg(int r,int s)4864 void move_reg(int r, int s)
4865 {
4866 SValue sv;
4867
4868 if (r != s) {
4869 save_reg(r);
4870 sv.type.t = VT_INT;
4871 sv.r = s;
4872 sv.c.ul = 0;
4873 load(r, &sv);
4874 }
4875 }
4876
4877 /* get address of vtop (vtop MUST BE an lvalue) */
gaddrof(void)4878 void gaddrof(void)
4879 {
4880 vtop->r &= ~VT_LVAL;
4881 /* tricky: if saved lvalue, then we can go back to lvalue */
4882 if ((vtop->r & VT_VALMASK) == VT_LLOCAL)
4883 vtop->r = (vtop->r & ~(VT_VALMASK | VT_LVAL_TYPE)) | VT_LOCAL | VT_LVAL;
4884 }
4885
4886 #ifdef CONFIG_TCC_BCHECK
4887 /* generate lvalue bound code */
gbound(void)4888 void gbound(void)
4889 {
4890 int lval_type;
4891 CType type1;
4892
4893 vtop->r &= ~VT_MUSTBOUND;
4894 /* if lvalue, then use checking code before dereferencing */
4895 if (vtop->r & VT_LVAL) {
4896 /* if not VT_BOUNDED value, then make one */
4897 if (!(vtop->r & VT_BOUNDED)) {
4898 lval_type = vtop->r & (VT_LVAL_TYPE | VT_LVAL);
4899 /* must save type because we must set it to int to get pointer */
4900 type1 = vtop->type;
4901 vtop->type.t = VT_INT;
4902 gaddrof();
4903 vpushi(0);
4904 gen_bounded_ptr_add();
4905 vtop->r |= lval_type;
4906 vtop->type = type1;
4907 }
4908 /* then check for dereferencing */
4909 gen_bounded_ptr_deref();
4910 }
4911 }
4912 #endif
4913
4914 /* store vtop a register belonging to class 'rc'. lvalues are
4915 converted to values. Cannot be used if cannot be converted to
4916 register value (such as structures). */
gv(int rc)4917 int gv(int rc)
4918 {
4919 int r, r2, rc2, bit_pos, bit_size, size, align, i;
4920 unsigned long long ll;
4921
4922 /* NOTE: get_reg can modify vstack[] */
4923 if (vtop->type.t & VT_BITFIELD) {
4924 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
4925 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
4926 /* remove bit field info to avoid loops */
4927 vtop->type.t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
4928 /* generate shifts */
4929 vpushi(32 - (bit_pos + bit_size));
4930 gen_op(TOK_SHL);
4931 vpushi(32 - bit_size);
4932 /* NOTE: transformed to SHR if unsigned */
4933 gen_op(TOK_SAR);
4934 r = gv(rc);
4935 } else {
4936 if (is_float(vtop->type.t) &&
4937 (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4938 Sym *sym;
4939 int *ptr;
4940 unsigned long offset;
4941 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4942 CValue check;
4943 #endif
4944
4945 /* XXX: unify with initializers handling ? */
4946 /* CPUs usually cannot use float constants, so we store them
4947 generically in data segment */
4948 size = type_size(&vtop->type, &align);
4949 offset = (data_section->data_offset + align - 1) & -align;
4950 data_section->data_offset = offset;
4951 /* XXX: not portable yet */
4952 #ifdef __i386__
4953 /* Zero pad x87 tenbyte long doubles */
4954 if (size == 12)
4955 vtop->c.tab[2] &= 0xffff;
4956 #endif
4957 ptr = section_ptr_add(data_section, size);
4958 size = size >> 2;
4959 #if defined(TCC_TARGET_ARM) && !defined(TCC_ARM_VFP)
4960 check.d = 1;
4961 if(check.tab[0])
4962 for(i=0;i<size;i++)
4963 ptr[i] = vtop->c.tab[size-1-i];
4964 else
4965 #endif
4966 for(i=0;i<size;i++)
4967 ptr[i] = vtop->c.tab[i];
4968 sym = get_sym_ref(&vtop->type, data_section, offset, size << 2);
4969 vtop->r |= VT_LVAL | VT_SYM;
4970 vtop->sym = sym;
4971 vtop->c.ul = 0;
4972 }
4973 #ifdef CONFIG_TCC_BCHECK
4974 if (vtop->r & VT_MUSTBOUND)
4975 gbound();
4976 #endif
4977
4978 r = vtop->r & VT_VALMASK;
4979 /* need to reload if:
4980 - constant
4981 - lvalue (need to dereference pointer)
4982 - already a register, but not in the right class */
4983 if (r >= VT_CONST ||
4984 (vtop->r & VT_LVAL) ||
4985 !(reg_classes[r] & rc) ||
4986 ((vtop->type.t & VT_BTYPE) == VT_LLONG &&
4987 !(reg_classes[vtop->r2] & rc))) {
4988 r = get_reg(rc);
4989 if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
4990 /* two register type load : expand to two words
4991 temporarily */
4992 if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
4993 /* load constant */
4994 ll = vtop->c.ull;
4995 vtop->c.ui = ll; /* first word */
4996 load(r, vtop);
4997 vtop->r = r; /* save register value */
4998 vpushi(ll >> 32); /* second word */
4999 } else if (r >= VT_CONST || /* XXX: test to VT_CONST incorrect ? */
5000 (vtop->r & VT_LVAL)) {
5001 /* We do not want to modifier the long long
5002 pointer here, so the safest (and less
5003 efficient) is to save all the other registers
5004 in the stack. XXX: totally inefficient. */
5005 save_regs(1);
5006 /* load from memory */
5007 load(r, vtop);
5008 vdup();
5009 vtop[-1].r = r; /* save register value */
5010 /* increment pointer to get second word */
5011 vtop->type.t = VT_INT;
5012 gaddrof();
5013 vpushi(4);
5014 gen_op('+');
5015 vtop->r |= VT_LVAL;
5016 } else {
5017 /* move registers */
5018 load(r, vtop);
5019 vdup();
5020 vtop[-1].r = r; /* save register value */
5021 vtop->r = vtop[-1].r2;
5022 }
5023 /* allocate second register */
5024 rc2 = RC_INT;
5025 if (rc == RC_IRET)
5026 rc2 = RC_LRET;
5027 r2 = get_reg(rc2);
5028 load(r2, vtop);
5029 vpop();
5030 /* write second register */
5031 vtop->r2 = r2;
5032 } else if ((vtop->r & VT_LVAL) && !is_float(vtop->type.t)) {
5033 int t1, t;
5034 /* lvalue of scalar type : need to use lvalue type
5035 because of possible cast */
5036 t = vtop->type.t;
5037 t1 = t;
5038 /* compute memory access type */
5039 if (vtop->r & VT_LVAL_BYTE)
5040 t = VT_BYTE;
5041 else if (vtop->r & VT_LVAL_SHORT)
5042 t = VT_SHORT;
5043 if (vtop->r & VT_LVAL_UNSIGNED)
5044 t |= VT_UNSIGNED;
5045 vtop->type.t = t;
5046 load(r, vtop);
5047 /* restore wanted type */
5048 vtop->type.t = t1;
5049 } else {
5050 /* one register type load */
5051 load(r, vtop);
5052 }
5053 }
5054 vtop->r = r;
5055 #ifdef TCC_TARGET_C67
5056 /* uses register pairs for doubles */
5057 if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
5058 vtop->r2 = r+1;
5059 #endif
5060 }
5061 return r;
5062 }
5063
5064 /* generate vtop[-1] and vtop[0] in resp. classes rc1 and rc2 */
gv2(int rc1,int rc2)5065 void gv2(int rc1, int rc2)
5066 {
5067 int v;
5068
5069 /* generate more generic register first. But VT_JMP or VT_CMP
5070 values must be generated first in all cases to avoid possible
5071 reload errors */
5072 v = vtop[0].r & VT_VALMASK;
5073 if (v != VT_CMP && (v & ~1) != VT_JMP && rc1 <= rc2) {
5074 vswap();
5075 gv(rc1);
5076 vswap();
5077 gv(rc2);
5078 /* test if reload is needed for first register */
5079 if ((vtop[-1].r & VT_VALMASK) >= VT_CONST) {
5080 vswap();
5081 gv(rc1);
5082 vswap();
5083 }
5084 } else {
5085 gv(rc2);
5086 vswap();
5087 gv(rc1);
5088 vswap();
5089 /* test if reload is needed for first register */
5090 if ((vtop[0].r & VT_VALMASK) >= VT_CONST) {
5091 gv(rc2);
5092 }
5093 }
5094 }
5095
5096 /* expand long long on stack in two int registers */
lexpand(void)5097 void lexpand(void)
5098 {
5099 int u;
5100
5101 u = vtop->type.t & VT_UNSIGNED;
5102 gv(RC_INT);
5103 vdup();
5104 vtop[0].r = vtop[-1].r2;
5105 vtop[0].r2 = VT_CONST;
5106 vtop[-1].r2 = VT_CONST;
5107 vtop[0].type.t = VT_INT | u;
5108 vtop[-1].type.t = VT_INT | u;
5109 }
5110
5111 #ifdef TCC_TARGET_ARM
5112 /* expand long long on stack */
lexpand_nr(void)5113 void lexpand_nr(void)
5114 {
5115 int u,v;
5116
5117 u = vtop->type.t & VT_UNSIGNED;
5118 vdup();
5119 vtop->r2 = VT_CONST;
5120 vtop->type.t = VT_INT | u;
5121 v=vtop[-1].r & (VT_VALMASK | VT_LVAL);
5122 if (v == VT_CONST) {
5123 vtop[-1].c.ui = vtop->c.ull;
5124 vtop->c.ui = vtop->c.ull >> 32;
5125 vtop->r = VT_CONST;
5126 } else if (v == (VT_LVAL|VT_CONST) || v == (VT_LVAL|VT_LOCAL)) {
5127 vtop->c.ui += 4;
5128 vtop->r = vtop[-1].r;
5129 } else if (v > VT_CONST) {
5130 vtop--;
5131 lexpand();
5132 } else
5133 vtop->r = vtop[-1].r2;
5134 vtop[-1].r2 = VT_CONST;
5135 vtop[-1].type.t = VT_INT | u;
5136 }
5137 #endif
5138
5139 /* build a long long from two ints */
lbuild(int t)5140 void lbuild(int t)
5141 {
5142 gv2(RC_INT, RC_INT);
5143 vtop[-1].r2 = vtop[0].r;
5144 vtop[-1].type.t = t;
5145 vpop();
5146 }
5147
5148 /* rotate n first stack elements to the bottom
5149 I1 ... In -> I2 ... In I1 [top is right]
5150 */
vrotb(int n)5151 void vrotb(int n)
5152 {
5153 int i;
5154 SValue tmp;
5155
5156 tmp = vtop[-n + 1];
5157 for(i=-n+1;i!=0;i++)
5158 vtop[i] = vtop[i+1];
5159 vtop[0] = tmp;
5160 }
5161
5162 /* rotate n first stack elements to the top
5163 I1 ... In -> In I1 ... I(n-1) [top is right]
5164 */
vrott(int n)5165 void vrott(int n)
5166 {
5167 int i;
5168 SValue tmp;
5169
5170 tmp = vtop[0];
5171 for(i = 0;i < n - 1; i++)
5172 vtop[-i] = vtop[-i - 1];
5173 vtop[-n + 1] = tmp;
5174 }
5175
5176 #ifdef TCC_TARGET_ARM
5177 /* like vrott but in other direction
5178 In ... I1 -> I(n-1) ... I1 In [top is right]
5179 */
vnrott(int n)5180 void vnrott(int n)
5181 {
5182 int i;
5183 SValue tmp;
5184
5185 tmp = vtop[-n + 1];
5186 for(i = n - 1; i > 0; i--)
5187 vtop[-i] = vtop[-i + 1];
5188 vtop[0] = tmp;
5189 }
5190 #endif
5191
5192 /* pop stack value */
vpop(void)5193 void vpop(void)
5194 {
5195 int v;
5196 v = vtop->r & VT_VALMASK;
5197 #ifdef TCC_TARGET_I386
5198 /* for x86, we need to pop the FP stack */
5199 if (v == TREG_ST0 && !nocode_wanted) {
5200 o(0xd9dd); /* fstp %st(1) */
5201 } else
5202 #endif
5203 if (v == VT_JMP || v == VT_JMPI) {
5204 /* need to put correct jump if && or || without test */
5205 gsym(vtop->c.ul);
5206 }
5207 vtop--;
5208 }
5209
5210 /* convert stack entry to register and duplicate its value in another
5211 register */
gv_dup(void)5212 void gv_dup(void)
5213 {
5214 int rc, t, r, r1;
5215 SValue sv;
5216
5217 t = vtop->type.t;
5218 if ((t & VT_BTYPE) == VT_LLONG) {
5219 lexpand();
5220 gv_dup();
5221 vswap();
5222 vrotb(3);
5223 gv_dup();
5224 vrotb(4);
5225 /* stack: H L L1 H1 */
5226 lbuild(t);
5227 vrotb(3);
5228 vrotb(3);
5229 vswap();
5230 lbuild(t);
5231 vswap();
5232 } else {
5233 /* duplicate value */
5234 rc = RC_INT;
5235 sv.type.t = VT_INT;
5236 if (is_float(t)) {
5237 rc = RC_FLOAT;
5238 sv.type.t = t;
5239 }
5240 r = gv(rc);
5241 r1 = get_reg(rc);
5242 sv.r = r;
5243 sv.c.ul = 0;
5244 load(r1, &sv); /* move r to r1 */
5245 vdup();
5246 /* duplicates value */
5247 vtop->r = r1;
5248 }
5249 }
5250
5251 /* generate CPU independent (unsigned) long long operations */
gen_opl(int op)5252 void gen_opl(int op)
5253 {
5254 int t, a, b, op1, c, i;
5255 int func;
5256 SValue tmp;
5257
5258 switch(op) {
5259 case '/':
5260 case TOK_PDIV:
5261 func = TOK___divdi3;
5262 goto gen_func;
5263 case TOK_UDIV:
5264 func = TOK___udivdi3;
5265 goto gen_func;
5266 case '%':
5267 func = TOK___moddi3;
5268 goto gen_func;
5269 case TOK_UMOD:
5270 func = TOK___umoddi3;
5271 gen_func:
5272 /* call generic long long function */
5273 vpush_global_sym(&func_old_type, func);
5274 vrott(3);
5275 gfunc_call(2);
5276 vpushi(0);
5277 vtop->r = REG_IRET;
5278 vtop->r2 = REG_LRET;
5279 break;
5280 case '^':
5281 case '&':
5282 case '|':
5283 case '*':
5284 case '+':
5285 case '-':
5286 t = vtop->type.t;
5287 vswap();
5288 lexpand();
5289 vrotb(3);
5290 lexpand();
5291 /* stack: L1 H1 L2 H2 */
5292 tmp = vtop[0];
5293 vtop[0] = vtop[-3];
5294 vtop[-3] = tmp;
5295 tmp = vtop[-2];
5296 vtop[-2] = vtop[-3];
5297 vtop[-3] = tmp;
5298 vswap();
5299 /* stack: H1 H2 L1 L2 */
5300 if (op == '*') {
5301 vpushv(vtop - 1);
5302 vpushv(vtop - 1);
5303 gen_op(TOK_UMULL);
5304 lexpand();
5305 /* stack: H1 H2 L1 L2 ML MH */
5306 for(i=0;i<4;i++)
5307 vrotb(6);
5308 /* stack: ML MH H1 H2 L1 L2 */
5309 tmp = vtop[0];
5310 vtop[0] = vtop[-2];
5311 vtop[-2] = tmp;
5312 /* stack: ML MH H1 L2 H2 L1 */
5313 gen_op('*');
5314 vrotb(3);
5315 vrotb(3);
5316 gen_op('*');
5317 /* stack: ML MH M1 M2 */
5318 gen_op('+');
5319 gen_op('+');
5320 } else if (op == '+' || op == '-') {
5321 /* XXX: add non carry method too (for MIPS or alpha) */
5322 if (op == '+')
5323 op1 = TOK_ADDC1;
5324 else
5325 op1 = TOK_SUBC1;
5326 gen_op(op1);
5327 /* stack: H1 H2 (L1 op L2) */
5328 vrotb(3);
5329 vrotb(3);
5330 gen_op(op1 + 1); /* TOK_xxxC2 */
5331 } else {
5332 gen_op(op);
5333 /* stack: H1 H2 (L1 op L2) */
5334 vrotb(3);
5335 vrotb(3);
5336 /* stack: (L1 op L2) H1 H2 */
5337 gen_op(op);
5338 /* stack: (L1 op L2) (H1 op H2) */
5339 }
5340 /* stack: L H */
5341 lbuild(t);
5342 break;
5343 case TOK_SAR:
5344 case TOK_SHR:
5345 case TOK_SHL:
5346 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST) {
5347 t = vtop[-1].type.t;
5348 vswap();
5349 lexpand();
5350 vrotb(3);
5351 /* stack: L H shift */
5352 c = (int)vtop->c.i;
5353 /* constant: simpler */
5354 /* NOTE: all comments are for SHL. the other cases are
5355 done by swaping words */
5356 vpop();
5357 if (op != TOK_SHL)
5358 vswap();
5359 if (c >= 32) {
5360 /* stack: L H */
5361 vpop();
5362 if (c > 32) {
5363 vpushi(c - 32);
5364 gen_op(op);
5365 }
5366 if (op != TOK_SAR) {
5367 vpushi(0);
5368 } else {
5369 gv_dup();
5370 vpushi(31);
5371 gen_op(TOK_SAR);
5372 }
5373 vswap();
5374 } else {
5375 vswap();
5376 gv_dup();
5377 /* stack: H L L */
5378 vpushi(c);
5379 gen_op(op);
5380 vswap();
5381 vpushi(32 - c);
5382 if (op == TOK_SHL)
5383 gen_op(TOK_SHR);
5384 else
5385 gen_op(TOK_SHL);
5386 vrotb(3);
5387 /* stack: L L H */
5388 vpushi(c);
5389 if (op == TOK_SHL)
5390 gen_op(TOK_SHL);
5391 else
5392 gen_op(TOK_SHR);
5393 gen_op('|');
5394 }
5395 if (op != TOK_SHL)
5396 vswap();
5397 lbuild(t);
5398 } else {
5399 /* XXX: should provide a faster fallback on x86 ? */
5400 switch(op) {
5401 case TOK_SAR:
5402 func = TOK___sardi3;
5403 goto gen_func;
5404 case TOK_SHR:
5405 func = TOK___shrdi3;
5406 goto gen_func;
5407 case TOK_SHL:
5408 func = TOK___shldi3;
5409 goto gen_func;
5410 }
5411 }
5412 break;
5413 default:
5414 /* compare operations */
5415 t = vtop->type.t;
5416 vswap();
5417 lexpand();
5418 vrotb(3);
5419 lexpand();
5420 /* stack: L1 H1 L2 H2 */
5421 tmp = vtop[-1];
5422 vtop[-1] = vtop[-2];
5423 vtop[-2] = tmp;
5424 /* stack: L1 L2 H1 H2 */
5425 /* compare high */
5426 op1 = op;
5427 /* when values are equal, we need to compare low words. since
5428 the jump is inverted, we invert the test too. */
5429 if (op1 == TOK_LT)
5430 op1 = TOK_LE;
5431 else if (op1 == TOK_GT)
5432 op1 = TOK_GE;
5433 else if (op1 == TOK_ULT)
5434 op1 = TOK_ULE;
5435 else if (op1 == TOK_UGT)
5436 op1 = TOK_UGE;
5437 a = 0;
5438 b = 0;
5439 gen_op(op1);
5440 if (op1 != TOK_NE) {
5441 a = gtst(1, 0);
5442 }
5443 if (op != TOK_EQ) {
5444 /* generate non equal test */
5445 /* XXX: NOT PORTABLE yet */
5446 if (a == 0) {
5447 b = gtst(0, 0);
5448 } else {
5449 #if defined(TCC_TARGET_I386)
5450 b = psym(0x850f, 0);
5451 #elif defined(TCC_TARGET_ARM)
5452 b = ind;
5453 o(0x1A000000 | encbranch(ind, 0, 1));
5454 #elif defined(TCC_TARGET_C67)
5455 error("not implemented");
5456 #else
5457 #error not supported
5458 #endif
5459 }
5460 }
5461 /* compare low. Always unsigned */
5462 op1 = op;
5463 if (op1 == TOK_LT)
5464 op1 = TOK_ULT;
5465 else if (op1 == TOK_LE)
5466 op1 = TOK_ULE;
5467 else if (op1 == TOK_GT)
5468 op1 = TOK_UGT;
5469 else if (op1 == TOK_GE)
5470 op1 = TOK_UGE;
5471 gen_op(op1);
5472 a = gtst(1, a);
5473 gsym(b);
5474 vseti(VT_JMPI, a);
5475 break;
5476 }
5477 }
5478
5479 /* handle integer constant optimizations and various machine
5480 independent opt */
gen_opic(int op)5481 void gen_opic(int op)
5482 {
5483 int c1, c2, t1, t2, n;
5484 SValue *v1, *v2;
5485 long long l1, l2;
5486 typedef unsigned long long U;
5487
5488 v1 = vtop - 1;
5489 v2 = vtop;
5490 t1 = v1->type.t & VT_BTYPE;
5491 t2 = v2->type.t & VT_BTYPE;
5492 l1 = (t1 == VT_LLONG) ? v1->c.ll : v1->c.i;
5493 l2 = (t2 == VT_LLONG) ? v2->c.ll : v2->c.i;
5494
5495 /* currently, we cannot do computations with forward symbols */
5496 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5497 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5498 if (c1 && c2) {
5499 switch(op) {
5500 case '+': l1 += l2; break;
5501 case '-': l1 -= l2; break;
5502 case '&': l1 &= l2; break;
5503 case '^': l1 ^= l2; break;
5504 case '|': l1 |= l2; break;
5505 case '*': l1 *= l2; break;
5506
5507 case TOK_PDIV:
5508 case '/':
5509 case '%':
5510 case TOK_UDIV:
5511 case TOK_UMOD:
5512 /* if division by zero, generate explicit division */
5513 if (l2 == 0) {
5514 if (const_wanted)
5515 error("division by zero in constant");
5516 goto general_case;
5517 }
5518 switch(op) {
5519 default: l1 /= l2; break;
5520 case '%': l1 %= l2; break;
5521 case TOK_UDIV: l1 = (U)l1 / l2; break;
5522 case TOK_UMOD: l1 = (U)l1 % l2; break;
5523 }
5524 break;
5525 case TOK_SHL: l1 <<= l2; break;
5526 case TOK_SHR: l1 = (U)l1 >> l2; break;
5527 case TOK_SAR: l1 >>= l2; break;
5528 /* tests */
5529 case TOK_ULT: l1 = (U)l1 < (U)l2; break;
5530 case TOK_UGE: l1 = (U)l1 >= (U)l2; break;
5531 case TOK_EQ: l1 = l1 == l2; break;
5532 case TOK_NE: l1 = l1 != l2; break;
5533 case TOK_ULE: l1 = (U)l1 <= (U)l2; break;
5534 case TOK_UGT: l1 = (U)l1 > (U)l2; break;
5535 case TOK_LT: l1 = l1 < l2; break;
5536 case TOK_GE: l1 = l1 >= l2; break;
5537 case TOK_LE: l1 = l1 <= l2; break;
5538 case TOK_GT: l1 = l1 > l2; break;
5539 /* logical */
5540 case TOK_LAND: l1 = l1 && l2; break;
5541 case TOK_LOR: l1 = l1 || l2; break;
5542 default:
5543 goto general_case;
5544 }
5545 v1->c.ll = l1;
5546 vtop--;
5547 } else {
5548 /* if commutative ops, put c2 as constant */
5549 if (c1 && (op == '+' || op == '&' || op == '^' ||
5550 op == '|' || op == '*')) {
5551 vswap();
5552 c2 = c1; //c = c1, c1 = c2, c2 = c;
5553 l2 = l1; //l = l1, l1 = l2, l2 = l;
5554 }
5555 /* Filter out NOP operations like x*1, x-0, x&-1... */
5556 if (c2 && (((op == '*' || op == '/' || op == TOK_UDIV ||
5557 op == TOK_PDIV) &&
5558 l2 == 1) ||
5559 ((op == '+' || op == '-' || op == '|' || op == '^' ||
5560 op == TOK_SHL || op == TOK_SHR || op == TOK_SAR) &&
5561 l2 == 0) ||
5562 (op == '&' &&
5563 l2 == -1))) {
5564 /* nothing to do */
5565 vtop--;
5566 } else if (c2 && (op == '*' || op == TOK_PDIV || op == TOK_UDIV)) {
5567 /* try to use shifts instead of muls or divs */
5568 if (l2 > 0 && (l2 & (l2 - 1)) == 0) {
5569 n = -1;
5570 while (l2) {
5571 l2 >>= 1;
5572 n++;
5573 }
5574 vtop->c.ll = n;
5575 if (op == '*')
5576 op = TOK_SHL;
5577 else if (op == TOK_PDIV)
5578 op = TOK_SAR;
5579 else
5580 op = TOK_SHR;
5581 }
5582 goto general_case;
5583 } else if (c2 && (op == '+' || op == '-') &&
5584 (vtop[-1].r & (VT_VALMASK | VT_LVAL | VT_SYM)) ==
5585 (VT_CONST | VT_SYM)) {
5586 /* symbol + constant case */
5587 if (op == '-')
5588 l2 = -l2;
5589 vtop--;
5590 vtop->c.ll += l2;
5591 } else {
5592 general_case:
5593 if (!nocode_wanted) {
5594 /* call low level op generator */
5595 if (t1 == VT_LLONG || t2 == VT_LLONG)
5596 gen_opl(op);
5597 else
5598 gen_opi(op);
5599 } else {
5600 vtop--;
5601 }
5602 }
5603 }
5604 }
5605
5606 /* generate a floating point operation with constant propagation */
gen_opif(int op)5607 void gen_opif(int op)
5608 {
5609 int c1, c2;
5610 SValue *v1, *v2;
5611 long double f1, f2;
5612
5613 v1 = vtop - 1;
5614 v2 = vtop;
5615 /* currently, we cannot do computations with forward symbols */
5616 c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5617 c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5618 if (c1 && c2) {
5619 if (v1->type.t == VT_FLOAT) {
5620 f1 = v1->c.f;
5621 f2 = v2->c.f;
5622 } else if (v1->type.t == VT_DOUBLE) {
5623 f1 = v1->c.d;
5624 f2 = v2->c.d;
5625 } else {
5626 f1 = v1->c.ld;
5627 f2 = v2->c.ld;
5628 }
5629
5630 /* NOTE: we only do constant propagation if finite number (not
5631 NaN or infinity) (ANSI spec) */
5632 if (!ieee_finite(f1) || !ieee_finite(f2))
5633 goto general_case;
5634
5635 switch(op) {
5636 case '+': f1 += f2; break;
5637 case '-': f1 -= f2; break;
5638 case '*': f1 *= f2; break;
5639 case '/':
5640 if (f2 == 0.0) {
5641 if (const_wanted)
5642 error("division by zero in constant");
5643 goto general_case;
5644 }
5645 f1 /= f2;
5646 break;
5647 /* XXX: also handles tests ? */
5648 default:
5649 goto general_case;
5650 }
5651 /* XXX: overflow test ? */
5652 if (v1->type.t == VT_FLOAT) {
5653 v1->c.f = f1;
5654 } else if (v1->type.t == VT_DOUBLE) {
5655 v1->c.d = f1;
5656 } else {
5657 v1->c.ld = f1;
5658 }
5659 vtop--;
5660 } else {
5661 general_case:
5662 if (!nocode_wanted) {
5663 gen_opf(op);
5664 } else {
5665 vtop--;
5666 }
5667 }
5668 }
5669
pointed_size(CType * type)5670 static int pointed_size(CType *type)
5671 {
5672 int align;
5673 return type_size(pointed_type(type), &align);
5674 }
5675
is_null_pointer(SValue * p)5676 static inline int is_null_pointer(SValue *p)
5677 {
5678 if ((p->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
5679 return 0;
5680 return ((p->type.t & VT_BTYPE) == VT_INT && p->c.i == 0) ||
5681 ((p->type.t & VT_BTYPE) == VT_LLONG && p->c.ll == 0);
5682 }
5683
is_integer_btype(int bt)5684 static inline int is_integer_btype(int bt)
5685 {
5686 return (bt == VT_BYTE || bt == VT_SHORT ||
5687 bt == VT_INT || bt == VT_LLONG);
5688 }
5689
5690 /* check types for comparison or substraction of pointers */
check_comparison_pointer_types(SValue * p1,SValue * p2,int op)5691 static void check_comparison_pointer_types(SValue *p1, SValue *p2, int op)
5692 {
5693 CType *type1, *type2, tmp_type1, tmp_type2;
5694 int bt1, bt2;
5695
5696 /* null pointers are accepted for all comparisons as gcc */
5697 if (is_null_pointer(p1) || is_null_pointer(p2))
5698 return;
5699 type1 = &p1->type;
5700 type2 = &p2->type;
5701 bt1 = type1->t & VT_BTYPE;
5702 bt2 = type2->t & VT_BTYPE;
5703 /* accept comparison between pointer and integer with a warning */
5704 if ((is_integer_btype(bt1) || is_integer_btype(bt2)) && op != '-') {
5705 if (op != TOK_LOR && op != TOK_LAND )
5706 warning("comparison between pointer and integer");
5707 return;
5708 }
5709
5710 /* both must be pointers or implicit function pointers */
5711 if (bt1 == VT_PTR) {
5712 type1 = pointed_type(type1);
5713 } else if (bt1 != VT_FUNC)
5714 goto invalid_operands;
5715
5716 if (bt2 == VT_PTR) {
5717 type2 = pointed_type(type2);
5718 } else if (bt2 != VT_FUNC) {
5719 invalid_operands:
5720 error("invalid operands to binary %s", get_tok_str(op, NULL));
5721 }
5722 if ((type1->t & VT_BTYPE) == VT_VOID ||
5723 (type2->t & VT_BTYPE) == VT_VOID)
5724 return;
5725 tmp_type1 = *type1;
5726 tmp_type2 = *type2;
5727 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5728 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
5729 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
5730 /* gcc-like error if '-' is used */
5731 if (op == '-')
5732 goto invalid_operands;
5733 else
5734 warning("comparison of distinct pointer types lacks a cast");
5735 }
5736 }
5737
5738 /* generic gen_op: handles types problems */
gen_op(int op)5739 void gen_op(int op)
5740 {
5741 int u, t1, t2, bt1, bt2, t;
5742 CType type1;
5743
5744 t1 = vtop[-1].type.t;
5745 t2 = vtop[0].type.t;
5746 bt1 = t1 & VT_BTYPE;
5747 bt2 = t2 & VT_BTYPE;
5748
5749 if (bt1 == VT_PTR || bt2 == VT_PTR) {
5750 /* at least one operand is a pointer */
5751 /* relationnal op: must be both pointers */
5752 if (op >= TOK_ULT && op <= TOK_LOR) {
5753 check_comparison_pointer_types(vtop - 1, vtop, op);
5754 /* pointers are handled are unsigned */
5755 t = VT_INT | VT_UNSIGNED;
5756 goto std_op;
5757 }
5758 /* if both pointers, then it must be the '-' op */
5759 if (bt1 == VT_PTR && bt2 == VT_PTR) {
5760 if (op != '-')
5761 error("cannot use pointers here");
5762 check_comparison_pointer_types(vtop - 1, vtop, op);
5763 /* XXX: check that types are compatible */
5764 u = pointed_size(&vtop[-1].type);
5765 gen_opic(op);
5766 /* set to integer type */
5767 vtop->type.t = VT_INT;
5768 vpushi(u);
5769 gen_op(TOK_PDIV);
5770 } else {
5771 /* exactly one pointer : must be '+' or '-'. */
5772 if (op != '-' && op != '+')
5773 error("cannot use pointers here");
5774 /* Put pointer as first operand */
5775 if (bt2 == VT_PTR) {
5776 vswap();
5777 swap(&t1, &t2);
5778 }
5779 type1 = vtop[-1].type;
5780 /* XXX: cast to int ? (long long case) */
5781 vpushi(pointed_size(&vtop[-1].type));
5782 gen_op('*');
5783 #ifdef CONFIG_TCC_BCHECK
5784 /* if evaluating constant expression, no code should be
5785 generated, so no bound check */
5786 if (do_bounds_check && !const_wanted) {
5787 /* if bounded pointers, we generate a special code to
5788 test bounds */
5789 if (op == '-') {
5790 vpushi(0);
5791 vswap();
5792 gen_op('-');
5793 }
5794 gen_bounded_ptr_add();
5795 } else
5796 #endif
5797 {
5798 gen_opic(op);
5799 }
5800 /* put again type if gen_opic() swaped operands */
5801 vtop->type = type1;
5802 }
5803 } else if (is_float(bt1) || is_float(bt2)) {
5804 /* compute bigger type and do implicit casts */
5805 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
5806 t = VT_LDOUBLE;
5807 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
5808 t = VT_DOUBLE;
5809 } else {
5810 t = VT_FLOAT;
5811 }
5812 /* floats can only be used for a few operations */
5813 if (op != '+' && op != '-' && op != '*' && op != '/' &&
5814 (op < TOK_ULT || op > TOK_GT))
5815 error("invalid operands for binary operation");
5816 goto std_op;
5817 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
5818 /* cast to biggest op */
5819 t = VT_LLONG;
5820 /* convert to unsigned if it does not fit in a long long */
5821 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
5822 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
5823 t |= VT_UNSIGNED;
5824 goto std_op;
5825 } else {
5826 /* integer operations */
5827 t = VT_INT;
5828 /* convert to unsigned if it does not fit in an integer */
5829 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
5830 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
5831 t |= VT_UNSIGNED;
5832 std_op:
5833 /* XXX: currently, some unsigned operations are explicit, so
5834 we modify them here */
5835 if (t & VT_UNSIGNED) {
5836 if (op == TOK_SAR)
5837 op = TOK_SHR;
5838 else if (op == '/')
5839 op = TOK_UDIV;
5840 else if (op == '%')
5841 op = TOK_UMOD;
5842 else if (op == TOK_LT)
5843 op = TOK_ULT;
5844 else if (op == TOK_GT)
5845 op = TOK_UGT;
5846 else if (op == TOK_LE)
5847 op = TOK_ULE;
5848 else if (op == TOK_GE)
5849 op = TOK_UGE;
5850 }
5851 vswap();
5852 type1.t = t;
5853 gen_cast(&type1);
5854 vswap();
5855 /* special case for shifts and long long: we keep the shift as
5856 an integer */
5857 if (op == TOK_SHR || op == TOK_SAR || op == TOK_SHL)
5858 type1.t = VT_INT;
5859 gen_cast(&type1);
5860 if (is_float(t))
5861 gen_opif(op);
5862 else
5863 gen_opic(op);
5864 if (op >= TOK_ULT && op <= TOK_GT) {
5865 /* relationnal op: the result is an int */
5866 vtop->type.t = VT_INT;
5867 } else {
5868 vtop->type.t = t;
5869 }
5870 }
5871 }
5872
5873 /* generic itof for unsigned long long case */
gen_cvt_itof1(int t)5874 void gen_cvt_itof1(int t)
5875 {
5876 if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
5877 (VT_LLONG | VT_UNSIGNED)) {
5878
5879 if (t == VT_FLOAT)
5880 vpush_global_sym(&func_old_type, TOK___ulltof);
5881 else if (t == VT_DOUBLE)
5882 vpush_global_sym(&func_old_type, TOK___ulltod);
5883 else
5884 vpush_global_sym(&func_old_type, TOK___ulltold);
5885 vrott(2);
5886 gfunc_call(1);
5887 vpushi(0);
5888 vtop->r = REG_FRET;
5889 } else {
5890 gen_cvt_itof(t);
5891 }
5892 }
5893
5894 /* generic ftoi for unsigned long long case */
gen_cvt_ftoi1(int t)5895 void gen_cvt_ftoi1(int t)
5896 {
5897 int st;
5898
5899 if (t == (VT_LLONG | VT_UNSIGNED)) {
5900 /* not handled natively */
5901 st = vtop->type.t & VT_BTYPE;
5902 if (st == VT_FLOAT)
5903 vpush_global_sym(&func_old_type, TOK___fixunssfdi);
5904 else if (st == VT_DOUBLE)
5905 vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
5906 else
5907 vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
5908 vrott(2);
5909 gfunc_call(1);
5910 vpushi(0);
5911 vtop->r = REG_IRET;
5912 vtop->r2 = REG_LRET;
5913 } else {
5914 gen_cvt_ftoi(t);
5915 }
5916 }
5917
5918 /* force char or short cast */
force_charshort_cast(int t)5919 void force_charshort_cast(int t)
5920 {
5921 int bits, dbt;
5922 dbt = t & VT_BTYPE;
5923 /* XXX: add optimization if lvalue : just change type and offset */
5924 if (dbt == VT_BYTE)
5925 bits = 8;
5926 else
5927 bits = 16;
5928 if (t & VT_UNSIGNED) {
5929 vpushi((1 << bits) - 1);
5930 gen_op('&');
5931 } else {
5932 bits = 32 - bits;
5933 vpushi(bits);
5934 gen_op(TOK_SHL);
5935 /* result must be signed or the SAR is converted to an SHL
5936 This was not the case when "t" was a signed short
5937 and the last value on the stack was an unsigned int */
5938 vtop->type.t &= ~VT_UNSIGNED;
5939 vpushi(bits);
5940 gen_op(TOK_SAR);
5941 }
5942 }
5943
5944 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
gen_cast(CType * type)5945 static void gen_cast(CType *type)
5946 {
5947 int sbt, dbt, sf, df, c;
5948
5949 /* special delayed cast for char/short */
5950 /* XXX: in some cases (multiple cascaded casts), it may still
5951 be incorrect */
5952 if (vtop->r & VT_MUSTCAST) {
5953 vtop->r &= ~VT_MUSTCAST;
5954 force_charshort_cast(vtop->type.t);
5955 }
5956
5957 /* bitfields first get cast to ints */
5958 if (vtop->type.t & VT_BITFIELD) {
5959 gv(RC_INT);
5960 }
5961
5962 dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
5963 sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
5964
5965 if (sbt != dbt && !nocode_wanted) {
5966 sf = is_float(sbt);
5967 df = is_float(dbt);
5968 c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
5969 if (sf && df) {
5970 /* convert from fp to fp */
5971 if (c) {
5972 /* constant case: we can do it now */
5973 /* XXX: in ISOC, cannot do it if error in convert */
5974 if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
5975 vtop->c.f = (float)vtop->c.d;
5976 else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
5977 vtop->c.f = (float)vtop->c.ld;
5978 else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
5979 vtop->c.d = (double)vtop->c.f;
5980 else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
5981 vtop->c.d = (double)vtop->c.ld;
5982 else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
5983 vtop->c.ld = (long double)vtop->c.f;
5984 else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
5985 vtop->c.ld = (long double)vtop->c.d;
5986 } else {
5987 /* non constant case: generate code */
5988 gen_cvt_ftof(dbt);
5989 }
5990 } else if (df) {
5991 /* convert int to fp */
5992 if (c) {
5993 switch(sbt) {
5994 case VT_LLONG | VT_UNSIGNED:
5995 case VT_LLONG:
5996 /* XXX: add const cases for long long */
5997 goto do_itof;
5998 case VT_INT | VT_UNSIGNED:
5999 switch(dbt) {
6000 case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
6001 case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
6002 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break;
6003 }
6004 break;
6005 default:
6006 switch(dbt) {
6007 case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
6008 case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
6009 case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
6010 }
6011 break;
6012 }
6013 } else {
6014 do_itof:
6015 #if !defined(TCC_TARGET_ARM)
6016 gen_cvt_itof1(dbt);
6017 #else
6018 gen_cvt_itof(dbt);
6019 #endif
6020 }
6021 } else if (sf) {
6022 /* convert fp to int */
6023 if (dbt == VT_BOOL) {
6024 vpushi(0);
6025 gen_op(TOK_NE);
6026 } else {
6027 /* we handle char/short/etc... with generic code */
6028 if (dbt != (VT_INT | VT_UNSIGNED) &&
6029 dbt != (VT_LLONG | VT_UNSIGNED) &&
6030 dbt != VT_LLONG)
6031 dbt = VT_INT;
6032 if (c) {
6033 switch(dbt) {
6034 case VT_LLONG | VT_UNSIGNED:
6035 case VT_LLONG:
6036 /* XXX: add const cases for long long */
6037 goto do_ftoi;
6038 case VT_INT | VT_UNSIGNED:
6039 switch(sbt) {
6040 case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
6041 case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
6042 case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break;
6043 }
6044 break;
6045 default:
6046 /* int case */
6047 switch(sbt) {
6048 case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break;
6049 case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break;
6050 case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break;
6051 }
6052 break;
6053 }
6054 } else {
6055 do_ftoi:
6056 gen_cvt_ftoi1(dbt);
6057 }
6058 if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) {
6059 /* additional cast for char/short... */
6060 vtop->type.t = dbt;
6061 gen_cast(type);
6062 }
6063 }
6064 } else if ((dbt & VT_BTYPE) == VT_LLONG) {
6065 if ((sbt & VT_BTYPE) != VT_LLONG) {
6066 /* scalar to long long */
6067 if (c) {
6068 if (sbt == (VT_INT | VT_UNSIGNED))
6069 vtop->c.ll = vtop->c.ui;
6070 else
6071 vtop->c.ll = vtop->c.i;
6072 } else {
6073 /* machine independent conversion */
6074 gv(RC_INT);
6075 /* generate high word */
6076 if (sbt == (VT_INT | VT_UNSIGNED)) {
6077 vpushi(0);
6078 gv(RC_INT);
6079 } else {
6080 gv_dup();
6081 vpushi(31);
6082 gen_op(TOK_SAR);
6083 }
6084 /* patch second register */
6085 vtop[-1].r2 = vtop->r;
6086 vpop();
6087 }
6088 }
6089 } else if (dbt == VT_BOOL) {
6090 /* scalar to bool */
6091 vpushi(0);
6092 gen_op(TOK_NE);
6093 } else if ((dbt & VT_BTYPE) == VT_BYTE ||
6094 (dbt & VT_BTYPE) == VT_SHORT) {
6095 if (sbt == VT_PTR) {
6096 vtop->type.t = VT_INT;
6097 warning("nonportable conversion from pointer to char/short");
6098 }
6099 force_charshort_cast(dbt);
6100 } else if ((dbt & VT_BTYPE) == VT_INT) {
6101 /* scalar to int */
6102 if (sbt == VT_LLONG) {
6103 /* from long long: just take low order word */
6104 lexpand();
6105 vpop();
6106 }
6107 /* if lvalue and single word type, nothing to do because
6108 the lvalue already contains the real type size (see
6109 VT_LVAL_xxx constants) */
6110 }
6111 } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) {
6112 /* if we are casting between pointer types,
6113 we must update the VT_LVAL_xxx size */
6114 vtop->r = (vtop->r & ~VT_LVAL_TYPE)
6115 | (lvalue_type(type->ref->type.t) & VT_LVAL_TYPE);
6116 }
6117 vtop->type = *type;
6118 }
6119
6120 /* return type size. Put alignment at 'a' */
type_size(CType * type,int * a)6121 static int type_size(CType *type, int *a)
6122 {
6123 Sym *s;
6124 int bt;
6125
6126 bt = type->t & VT_BTYPE;
6127 if (bt == VT_STRUCT) {
6128 /* struct/union */
6129 s = type->ref;
6130 *a = s->r;
6131 return s->c;
6132 } else if (bt == VT_PTR) {
6133 if (type->t & VT_ARRAY) {
6134 s = type->ref;
6135 return type_size(&s->type, a) * s->c;
6136 } else {
6137 *a = PTR_SIZE;
6138 return PTR_SIZE;
6139 }
6140 } else if (bt == VT_LDOUBLE) {
6141 *a = LDOUBLE_ALIGN;
6142 return LDOUBLE_SIZE;
6143 } else if (bt == VT_DOUBLE || bt == VT_LLONG) {
6144 #ifdef TCC_TARGET_I386
6145 *a = 4;
6146 #elif defined(TCC_TARGET_ARM)
6147 #ifdef TCC_ARM_EABI
6148 *a = 8;
6149 #else
6150 *a = 4;
6151 #endif
6152 #else
6153 *a = 8;
6154 #endif
6155 return 8;
6156 } else if (bt == VT_INT || bt == VT_ENUM || bt == VT_FLOAT) {
6157 *a = 4;
6158 return 4;
6159 } else if (bt == VT_SHORT) {
6160 *a = 2;
6161 return 2;
6162 } else {
6163 /* char, void, function, _Bool */
6164 *a = 1;
6165 return 1;
6166 }
6167 }
6168
6169 /* return the pointed type of t */
pointed_type(CType * type)6170 static inline CType *pointed_type(CType *type)
6171 {
6172 return &type->ref->type;
6173 }
6174
6175 /* modify type so that its it is a pointer to type. */
mk_pointer(CType * type)6176 static void mk_pointer(CType *type)
6177 {
6178 Sym *s;
6179 s = sym_push(SYM_FIELD, type, 0, -1);
6180 type->t = VT_PTR | (type->t & ~VT_TYPE);
6181 type->ref = s;
6182 }
6183
6184 /* compare function types. OLD functions match any new functions */
is_compatible_func(CType * type1,CType * type2)6185 static int is_compatible_func(CType *type1, CType *type2)
6186 {
6187 Sym *s1, *s2;
6188
6189 s1 = type1->ref;
6190 s2 = type2->ref;
6191 if (!is_compatible_types(&s1->type, &s2->type))
6192 return 0;
6193 /* check func_call */
6194 if (FUNC_CALL(s1->r) != FUNC_CALL(s2->r))
6195 return 0;
6196 /* XXX: not complete */
6197 if (s1->c == FUNC_OLD || s2->c == FUNC_OLD)
6198 return 1;
6199 if (s1->c != s2->c)
6200 return 0;
6201 while (s1 != NULL) {
6202 if (s2 == NULL)
6203 return 0;
6204 if (!is_compatible_parameter_types(&s1->type, &s2->type))
6205 return 0;
6206 s1 = s1->next;
6207 s2 = s2->next;
6208 }
6209 if (s2)
6210 return 0;
6211 return 1;
6212 }
6213
6214 /* return true if type1 and type2 are the same. If unqualified is
6215 true, qualifiers on the types are ignored.
6216
6217 - enums are not checked as gcc __builtin_types_compatible_p ()
6218 */
compare_types(CType * type1,CType * type2,int unqualified)6219 static int compare_types(CType *type1, CType *type2, int unqualified)
6220 {
6221 int bt1, t1, t2;
6222
6223 t1 = type1->t & VT_TYPE;
6224 t2 = type2->t & VT_TYPE;
6225 if (unqualified) {
6226 /* strip qualifiers before comparing */
6227 t1 &= ~(VT_CONSTANT | VT_VOLATILE);
6228 t2 &= ~(VT_CONSTANT | VT_VOLATILE);
6229 }
6230 /* XXX: bitfields ? */
6231 if (t1 != t2)
6232 return 0;
6233 /* test more complicated cases */
6234 bt1 = t1 & VT_BTYPE;
6235 if (bt1 == VT_PTR) {
6236 type1 = pointed_type(type1);
6237 type2 = pointed_type(type2);
6238 return is_compatible_types(type1, type2);
6239 } else if (bt1 == VT_STRUCT) {
6240 return (type1->ref == type2->ref);
6241 } else if (bt1 == VT_FUNC) {
6242 return is_compatible_func(type1, type2);
6243 } else {
6244 return 1;
6245 }
6246 }
6247
6248 /* return true if type1 and type2 are exactly the same (including
6249 qualifiers).
6250 */
is_compatible_types(CType * type1,CType * type2)6251 static int is_compatible_types(CType *type1, CType *type2)
6252 {
6253 return compare_types(type1,type2,0);
6254 }
6255
6256 /* return true if type1 and type2 are the same (ignoring qualifiers).
6257 */
is_compatible_parameter_types(CType * type1,CType * type2)6258 static int is_compatible_parameter_types(CType *type1, CType *type2)
6259 {
6260 return compare_types(type1,type2,1);
6261 }
6262
6263 /* print a type. If 'varstr' is not NULL, then the variable is also
6264 printed in the type */
6265 /* XXX: union */
6266 /* XXX: add array and function pointers */
type_to_str(char * buf,int buf_size,CType * type,const char * varstr)6267 void type_to_str(char *buf, int buf_size,
6268 CType *type, const char *varstr)
6269 {
6270 int bt, v, t;
6271 Sym *s, *sa;
6272 char buf1[256];
6273 const char *tstr;
6274
6275 t = type->t & VT_TYPE;
6276 bt = t & VT_BTYPE;
6277 buf[0] = '\0';
6278 if (t & VT_CONSTANT)
6279 pstrcat(buf, buf_size, "const ");
6280 if (t & VT_VOLATILE)
6281 pstrcat(buf, buf_size, "volatile ");
6282 if (t & VT_UNSIGNED)
6283 pstrcat(buf, buf_size, "unsigned ");
6284 switch(bt) {
6285 case VT_VOID:
6286 tstr = "void";
6287 goto add_tstr;
6288 case VT_BOOL:
6289 tstr = "_Bool";
6290 goto add_tstr;
6291 case VT_BYTE:
6292 tstr = "char";
6293 goto add_tstr;
6294 case VT_SHORT:
6295 tstr = "short";
6296 goto add_tstr;
6297 case VT_INT:
6298 tstr = "int";
6299 goto add_tstr;
6300 case VT_LONG:
6301 tstr = "long";
6302 goto add_tstr;
6303 case VT_LLONG:
6304 tstr = "long long";
6305 goto add_tstr;
6306 case VT_FLOAT:
6307 tstr = "float";
6308 goto add_tstr;
6309 case VT_DOUBLE:
6310 tstr = "double";
6311 goto add_tstr;
6312 case VT_LDOUBLE:
6313 tstr = "long double";
6314 add_tstr:
6315 pstrcat(buf, buf_size, tstr);
6316 break;
6317 case VT_ENUM:
6318 case VT_STRUCT:
6319 if (bt == VT_STRUCT)
6320 tstr = "struct ";
6321 else
6322 tstr = "enum ";
6323 pstrcat(buf, buf_size, tstr);
6324 v = type->ref->v & ~SYM_STRUCT;
6325 if (v >= SYM_FIRST_ANOM)
6326 pstrcat(buf, buf_size, "<anonymous>");
6327 else
6328 pstrcat(buf, buf_size, get_tok_str(v, NULL));
6329 break;
6330 case VT_FUNC:
6331 s = type->ref;
6332 type_to_str(buf, buf_size, &s->type, varstr);
6333 pstrcat(buf, buf_size, "(");
6334 sa = s->next;
6335 while (sa != NULL) {
6336 type_to_str(buf1, sizeof(buf1), &sa->type, NULL);
6337 pstrcat(buf, buf_size, buf1);
6338 sa = sa->next;
6339 if (sa)
6340 pstrcat(buf, buf_size, ", ");
6341 }
6342 pstrcat(buf, buf_size, ")");
6343 goto no_var;
6344 case VT_PTR:
6345 s = type->ref;
6346 pstrcpy(buf1, sizeof(buf1), "*");
6347 if (varstr)
6348 pstrcat(buf1, sizeof(buf1), varstr);
6349 type_to_str(buf, buf_size, &s->type, buf1);
6350 goto no_var;
6351 }
6352 if (varstr) {
6353 pstrcat(buf, buf_size, " ");
6354 pstrcat(buf, buf_size, varstr);
6355 }
6356 no_var: ;
6357 }
6358
6359 /* verify type compatibility to store vtop in 'dt' type, and generate
6360 casts if needed. */
gen_assign_cast(CType * dt)6361 static void gen_assign_cast(CType *dt)
6362 {
6363 CType *st, *type1, *type2, tmp_type1, tmp_type2;
6364 char buf1[256], buf2[256];
6365 int dbt, sbt;
6366
6367 st = &vtop->type; /* source type */
6368 dbt = dt->t & VT_BTYPE;
6369 sbt = st->t & VT_BTYPE;
6370 if (dt->t & VT_CONSTANT)
6371 warning("assignment of read-only location");
6372 switch(dbt) {
6373 case VT_PTR:
6374 /* special cases for pointers */
6375 /* '0' can also be a pointer */
6376 if (is_null_pointer(vtop))
6377 goto type_ok;
6378 /* accept implicit pointer to integer cast with warning */
6379 if (is_integer_btype(sbt)) {
6380 warning("assignment makes pointer from integer without a cast");
6381 goto type_ok;
6382 }
6383 type1 = pointed_type(dt);
6384 /* a function is implicitely a function pointer */
6385 if (sbt == VT_FUNC) {
6386 if ((type1->t & VT_BTYPE) != VT_VOID &&
6387 !is_compatible_types(pointed_type(dt), st))
6388 goto error;
6389 else
6390 goto type_ok;
6391 }
6392 if (sbt != VT_PTR)
6393 goto error;
6394 type2 = pointed_type(st);
6395 if ((type1->t & VT_BTYPE) == VT_VOID ||
6396 (type2->t & VT_BTYPE) == VT_VOID) {
6397 /* void * can match anything */
6398 } else {
6399 /* exact type match, except for unsigned */
6400 tmp_type1 = *type1;
6401 tmp_type2 = *type2;
6402 tmp_type1.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6403 tmp_type2.t &= ~(VT_UNSIGNED | VT_CONSTANT | VT_VOLATILE);
6404 if (!is_compatible_types(&tmp_type1, &tmp_type2))
6405 warning("assignment from incompatible pointer type");
6406 }
6407 /* check const and volatile */
6408 if ((!(type1->t & VT_CONSTANT) && (type2->t & VT_CONSTANT)) ||
6409 (!(type1->t & VT_VOLATILE) && (type2->t & VT_VOLATILE)))
6410 warning("assignment discards qualifiers from pointer target type");
6411 break;
6412 case VT_BYTE:
6413 case VT_SHORT:
6414 case VT_INT:
6415 case VT_LLONG:
6416 if (sbt == VT_PTR || sbt == VT_FUNC) {
6417 warning("assignment makes integer from pointer without a cast");
6418 }
6419 /* XXX: more tests */
6420 break;
6421 case VT_STRUCT:
6422 tmp_type1 = *dt;
6423 tmp_type2 = *st;
6424 tmp_type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
6425 tmp_type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
6426 if (!is_compatible_types(&tmp_type1, &tmp_type2)) {
6427 error:
6428 type_to_str(buf1, sizeof(buf1), st, NULL);
6429 type_to_str(buf2, sizeof(buf2), dt, NULL);
6430 error("cannot cast '%s' to '%s'", buf1, buf2);
6431 }
6432 break;
6433 }
6434 type_ok:
6435 gen_cast(dt);
6436 }
6437
6438 /* store vtop in lvalue pushed on stack */
vstore(void)6439 void vstore(void)
6440 {
6441 int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
6442
6443 ft = vtop[-1].type.t;
6444 sbt = vtop->type.t & VT_BTYPE;
6445 dbt = ft & VT_BTYPE;
6446 if (((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
6447 (sbt == VT_INT && dbt == VT_SHORT)) {
6448 /* optimize char/short casts */
6449 delayed_cast = VT_MUSTCAST;
6450 vtop->type.t = ft & VT_TYPE;
6451 /* XXX: factorize */
6452 if (ft & VT_CONSTANT)
6453 warning("assignment of read-only location");
6454 } else {
6455 delayed_cast = 0;
6456 if (!(ft & VT_BITFIELD))
6457 gen_assign_cast(&vtop[-1].type);
6458 }
6459
6460 if (sbt == VT_STRUCT) {
6461 /* if structure, only generate pointer */
6462 /* structure assignment : generate memcpy */
6463 /* XXX: optimize if small size */
6464 if (!nocode_wanted) {
6465 size = type_size(&vtop->type, &align);
6466
6467 #ifdef TCC_ARM_EABI
6468 if(!(align & 7))
6469 vpush_global_sym(&func_old_type, TOK_memcpy8);
6470 else if(!(align & 3))
6471 vpush_global_sym(&func_old_type, TOK_memcpy4);
6472 else
6473 #endif
6474 vpush_global_sym(&func_old_type, TOK_memcpy);
6475
6476 /* destination */
6477 vpushv(vtop - 2);
6478 vtop->type.t = VT_INT;
6479 gaddrof();
6480 /* source */
6481 vpushv(vtop - 2);
6482 vtop->type.t = VT_INT;
6483 gaddrof();
6484 /* type size */
6485 vpushi(size);
6486 gfunc_call(3);
6487
6488 vswap();
6489 vpop();
6490 } else {
6491 vswap();
6492 vpop();
6493 }
6494 /* leave source on stack */
6495 } else if (ft & VT_BITFIELD) {
6496 /* bitfield store handling */
6497 bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
6498 bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
6499 /* remove bit field info to avoid loops */
6500 vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
6501
6502 /* duplicate source into other register */
6503 gv_dup();
6504 vswap();
6505 vrott(3);
6506
6507 /* duplicate destination */
6508 vdup();
6509 vtop[-1] = vtop[-2];
6510
6511 /* mask and shift source */
6512 vpushi((1 << bit_size) - 1);
6513 gen_op('&');
6514 vpushi(bit_pos);
6515 gen_op(TOK_SHL);
6516 /* load destination, mask and or with source */
6517 vswap();
6518 vpushi(~(((1 << bit_size) - 1) << bit_pos));
6519 gen_op('&');
6520 gen_op('|');
6521 /* store result */
6522 vstore();
6523
6524 /* pop off shifted source from "duplicate source..." above */
6525 vpop();
6526
6527 } else {
6528 #ifdef CONFIG_TCC_BCHECK
6529 /* bound check case */
6530 if (vtop[-1].r & VT_MUSTBOUND) {
6531 vswap();
6532 gbound();
6533 vswap();
6534 }
6535 #endif
6536 if (!nocode_wanted) {
6537 rc = RC_INT;
6538 if (is_float(ft))
6539 rc = RC_FLOAT;
6540 r = gv(rc); /* generate value */
6541 /* if lvalue was saved on stack, must read it */
6542 if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) {
6543 SValue sv;
6544 t = get_reg(RC_INT);
6545 sv.type.t = VT_INT;
6546 sv.r = VT_LOCAL | VT_LVAL;
6547 sv.c.ul = vtop[-1].c.ul;
6548 load(t, &sv);
6549 vtop[-1].r = t | VT_LVAL;
6550 }
6551 store(r, vtop - 1);
6552 /* two word case handling : store second register at word + 4 */
6553 if ((ft & VT_BTYPE) == VT_LLONG) {
6554 vswap();
6555 /* convert to int to increment easily */
6556 vtop->type.t = VT_INT;
6557 gaddrof();
6558 vpushi(4);
6559 gen_op('+');
6560 vtop->r |= VT_LVAL;
6561 vswap();
6562 /* XXX: it works because r2 is spilled last ! */
6563 store(vtop->r2, vtop - 1);
6564 }
6565 }
6566 vswap();
6567 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6568 vtop->r |= delayed_cast;
6569 }
6570 }
6571
6572 /* post defines POST/PRE add. c is the token ++ or -- */
inc(int post,int c)6573 void inc(int post, int c)
6574 {
6575 test_lvalue();
6576 vdup(); /* save lvalue */
6577 if (post) {
6578 gv_dup(); /* duplicate value */
6579 vrotb(3);
6580 vrotb(3);
6581 }
6582 /* add constant */
6583 vpushi(c - TOK_MID);
6584 gen_op('+');
6585 vstore(); /* store value */
6586 if (post)
6587 vpop(); /* if post op, return saved value */
6588 }
6589
6590 /* Parse GNUC __attribute__ extension. Currently, the following
6591 extensions are recognized:
6592 - aligned(n) : set data/function alignment.
6593 - packed : force data alignment to 1
6594 - section(x) : generate data/code in this section.
6595 - unused : currently ignored, but may be used someday.
6596 - regparm(n) : pass function parameters in registers (i386 only)
6597 */
parse_attribute(AttributeDef * ad)6598 static void parse_attribute(AttributeDef *ad)
6599 {
6600 int t, n;
6601
6602 while (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2) {
6603 next();
6604 skip('(');
6605 skip('(');
6606 while (tok != ')') {
6607 if (tok < TOK_IDENT)
6608 expect("attribute name");
6609 t = tok;
6610 next();
6611 switch(t) {
6612 case TOK_SECTION1:
6613 case TOK_SECTION2:
6614 skip('(');
6615 if (tok != TOK_STR)
6616 expect("section name");
6617 ad->section = find_section(tcc_state, (char *)tokc.cstr->data);
6618 next();
6619 skip(')');
6620 break;
6621 case TOK_ALIGNED1:
6622 case TOK_ALIGNED2:
6623 if (tok == '(') {
6624 next();
6625 n = expr_const();
6626 if (n <= 0 || (n & (n - 1)) != 0)
6627 error("alignment must be a positive power of two");
6628 skip(')');
6629 } else {
6630 n = MAX_ALIGN;
6631 }
6632 ad->aligned = n;
6633 break;
6634 case TOK_PACKED1:
6635 case TOK_PACKED2:
6636 ad->packed = 1;
6637 break;
6638 case TOK_UNUSED1:
6639 case TOK_UNUSED2:
6640 /* currently, no need to handle it because tcc does not
6641 track unused objects */
6642 break;
6643 case TOK_NORETURN1:
6644 case TOK_NORETURN2:
6645 /* currently, no need to handle it because tcc does not
6646 track unused objects */
6647 break;
6648 case TOK_CDECL1:
6649 case TOK_CDECL2:
6650 case TOK_CDECL3:
6651 FUNC_CALL(ad->func_attr) = FUNC_CDECL;
6652 break;
6653 case TOK_STDCALL1:
6654 case TOK_STDCALL2:
6655 case TOK_STDCALL3:
6656 FUNC_CALL(ad->func_attr) = FUNC_STDCALL;
6657 break;
6658 #ifdef TCC_TARGET_I386
6659 case TOK_REGPARM1:
6660 case TOK_REGPARM2:
6661 skip('(');
6662 n = expr_const();
6663 if (n > 3)
6664 n = 3;
6665 else if (n < 0)
6666 n = 0;
6667 if (n > 0)
6668 FUNC_CALL(ad->func_attr) = FUNC_FASTCALL1 + n - 1;
6669 skip(')');
6670 break;
6671 case TOK_FASTCALL1:
6672 case TOK_FASTCALL2:
6673 case TOK_FASTCALL3:
6674 FUNC_CALL(ad->func_attr) = FUNC_FASTCALLW;
6675 break;
6676 #endif
6677 case TOK_DLLEXPORT:
6678 FUNC_EXPORT(ad->func_attr) = 1;
6679 break;
6680 default:
6681 if (tcc_state->warn_unsupported)
6682 warning("'%s' attribute ignored", get_tok_str(t, NULL));
6683 /* skip parameters */
6684 if (tok == '(') {
6685 int parenthesis = 0;
6686 do {
6687 if (tok == '(')
6688 parenthesis++;
6689 else if (tok == ')')
6690 parenthesis--;
6691 next();
6692 } while (parenthesis && tok != -1);
6693 }
6694 break;
6695 }
6696 if (tok != ',')
6697 break;
6698 next();
6699 }
6700 skip(')');
6701 skip(')');
6702 }
6703 }
6704
6705 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
struct_decl(CType * type,int u)6706 static void struct_decl(CType *type, int u)
6707 {
6708 int a, v, size, align, maxalign, c, offset;
6709 int bit_size, bit_pos, bsize, bt, lbit_pos;
6710 Sym *s, *ss, *ass, **ps;
6711 AttributeDef ad;
6712 CType type1, btype;
6713
6714 a = tok; /* save decl type */
6715 next();
6716 if (tok != '{') {
6717 v = tok;
6718 next();
6719 /* struct already defined ? return it */
6720 if (v < TOK_IDENT)
6721 expect("struct/union/enum name");
6722 s = struct_find(v);
6723 if (s) {
6724 if (s->type.t != a)
6725 error("invalid type");
6726 goto do_decl;
6727 }
6728 } else {
6729 v = anon_sym++;
6730 }
6731 type1.t = a;
6732 /* we put an undefined size for struct/union */
6733 s = sym_push(v | SYM_STRUCT, &type1, 0, -1);
6734 s->r = 0; /* default alignment is zero as gcc */
6735 /* put struct/union/enum name in type */
6736 do_decl:
6737 type->t = u;
6738 type->ref = s;
6739
6740 if (tok == '{') {
6741 next();
6742 if (s->c != -1)
6743 error("struct/union/enum already defined");
6744 /* cannot be empty */
6745 c = 0;
6746 /* non empty enums are not allowed */
6747 if (a == TOK_ENUM) {
6748 for(;;) {
6749 v = tok;
6750 if (v < TOK_UIDENT)
6751 expect("identifier");
6752 next();
6753 if (tok == '=') {
6754 next();
6755 c = expr_const();
6756 }
6757 /* enum symbols have static storage */
6758 ss = sym_push(v, &int_type, VT_CONST, c);
6759 ss->type.t |= VT_STATIC;
6760 if (tok != ',')
6761 break;
6762 next();
6763 c++;
6764 /* NOTE: we accept a trailing comma */
6765 if (tok == '}')
6766 break;
6767 }
6768 skip('}');
6769 } else {
6770 maxalign = 1;
6771 ps = &s->next;
6772 bit_pos = 0;
6773 offset = 0;
6774 while (tok != '}') {
6775 parse_btype(&btype, &ad);
6776 while (1) {
6777 bit_size = -1;
6778 v = 0;
6779 type1 = btype;
6780 if (tok != ':') {
6781 type_decl(&type1, &ad, &v, TYPE_DIRECT | TYPE_ABSTRACT);
6782 if (v == 0 && (type1.t & VT_BTYPE) != VT_STRUCT)
6783 expect("identifier");
6784 if ((type1.t & VT_BTYPE) == VT_FUNC ||
6785 (type1.t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN | VT_INLINE)))
6786 error("invalid type for '%s'",
6787 get_tok_str(v, NULL));
6788 }
6789 if (tok == ':') {
6790 next();
6791 bit_size = expr_const();
6792 /* XXX: handle v = 0 case for messages */
6793 if (bit_size < 0)
6794 error("negative width in bit-field '%s'",
6795 get_tok_str(v, NULL));
6796 if (v && bit_size == 0)
6797 error("zero width for bit-field '%s'",
6798 get_tok_str(v, NULL));
6799 }
6800 size = type_size(&type1, &align);
6801 if (ad.aligned) {
6802 if (align < ad.aligned)
6803 align = ad.aligned;
6804 } else if (ad.packed) {
6805 align = 1;
6806 } else if (*tcc_state->pack_stack_ptr) {
6807 if (align > *tcc_state->pack_stack_ptr)
6808 align = *tcc_state->pack_stack_ptr;
6809 }
6810 lbit_pos = 0;
6811 if (bit_size >= 0) {
6812 bt = type1.t & VT_BTYPE;
6813 if (bt != VT_INT &&
6814 bt != VT_BYTE &&
6815 bt != VT_SHORT &&
6816 bt != VT_BOOL &&
6817 bt != VT_ENUM)
6818 error("bitfields must have scalar type");
6819 bsize = size * 8;
6820 if (bit_size > bsize) {
6821 error("width of '%s' exceeds its type",
6822 get_tok_str(v, NULL));
6823 } else if (bit_size == bsize) {
6824 /* no need for bit fields */
6825 bit_pos = 0;
6826 } else if (bit_size == 0) {
6827 /* XXX: what to do if only padding in a
6828 structure ? */
6829 /* zero size: means to pad */
6830 if (bit_pos > 0)
6831 bit_pos = bsize;
6832 } else {
6833 /* we do not have enough room ? */
6834 if ((bit_pos + bit_size) > bsize)
6835 bit_pos = 0;
6836 lbit_pos = bit_pos;
6837 /* XXX: handle LSB first */
6838 type1.t |= VT_BITFIELD |
6839 (bit_pos << VT_STRUCT_SHIFT) |
6840 (bit_size << (VT_STRUCT_SHIFT + 6));
6841 bit_pos += bit_size;
6842 }
6843 } else {
6844 bit_pos = 0;
6845 }
6846 if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
6847 /* add new memory data only if starting
6848 bit field */
6849 if (lbit_pos == 0) {
6850 if (a == TOK_STRUCT) {
6851 c = (c + align - 1) & -align;
6852 offset = c;
6853 if (size > 0)
6854 c += size;
6855 } else {
6856 offset = 0;
6857 if (size > c)
6858 c = size;
6859 }
6860 if (align > maxalign)
6861 maxalign = align;
6862 }
6863 #if 0
6864 printf("add field %s offset=%d",
6865 get_tok_str(v, NULL), offset);
6866 if (type1.t & VT_BITFIELD) {
6867 printf(" pos=%d size=%d",
6868 (type1.t >> VT_STRUCT_SHIFT) & 0x3f,
6869 (type1.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
6870 }
6871 printf("\n");
6872 #endif
6873 }
6874 if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) {
6875 ass = type1.ref;
6876 while ((ass = ass->next) != NULL) {
6877 ss = sym_push(ass->v, &ass->type, 0, offset + ass->c);
6878 *ps = ss;
6879 ps = &ss->next;
6880 }
6881 } else if (v) {
6882 ss = sym_push(v | SYM_FIELD, &type1, 0, offset);
6883 *ps = ss;
6884 ps = &ss->next;
6885 }
6886 if (tok == ';' || tok == TOK_EOF)
6887 break;
6888 skip(',');
6889 }
6890 skip(';');
6891 }
6892 skip('}');
6893 /* store size and alignment */
6894 s->c = (c + maxalign - 1) & -maxalign;
6895 s->r = maxalign;
6896 }
6897 }
6898 }
6899
6900 /* return 0 if no type declaration. otherwise, return the basic type
6901 and skip it.
6902 */
parse_btype(CType * type,AttributeDef * ad)6903 static int parse_btype(CType *type, AttributeDef *ad)
6904 {
6905 int t, u, type_found, typespec_found, typedef_found;
6906 Sym *s;
6907 CType type1;
6908
6909 memset(ad, 0, sizeof(AttributeDef));
6910 type_found = 0;
6911 typespec_found = 0;
6912 typedef_found = 0;
6913 t = 0;
6914 while(1) {
6915 switch(tok) {
6916 case TOK_EXTENSION:
6917 /* currently, we really ignore extension */
6918 next();
6919 continue;
6920
6921 /* basic types */
6922 case TOK_CHAR:
6923 u = VT_BYTE;
6924 basic_type:
6925 next();
6926 basic_type1:
6927 if ((t & VT_BTYPE) != 0)
6928 error("too many basic types");
6929 t |= u;
6930 typespec_found = 1;
6931 break;
6932 case TOK_VOID:
6933 u = VT_VOID;
6934 goto basic_type;
6935 case TOK_SHORT:
6936 u = VT_SHORT;
6937 goto basic_type;
6938 case TOK_INT:
6939 next();
6940 typespec_found = 1;
6941 break;
6942 case TOK_LONG:
6943 next();
6944 if ((t & VT_BTYPE) == VT_DOUBLE) {
6945 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6946 } else if ((t & VT_BTYPE) == VT_LONG) {
6947 t = (t & ~VT_BTYPE) | VT_LLONG;
6948 } else {
6949 u = VT_LONG;
6950 goto basic_type1;
6951 }
6952 break;
6953 case TOK_BOOL:
6954 u = VT_BOOL;
6955 goto basic_type;
6956 case TOK_FLOAT:
6957 u = VT_FLOAT;
6958 goto basic_type;
6959 case TOK_DOUBLE:
6960 next();
6961 if ((t & VT_BTYPE) == VT_LONG) {
6962 t = (t & ~VT_BTYPE) | VT_LDOUBLE;
6963 } else {
6964 u = VT_DOUBLE;
6965 goto basic_type1;
6966 }
6967 break;
6968 case TOK_ENUM:
6969 struct_decl(&type1, VT_ENUM);
6970 basic_type2:
6971 u = type1.t;
6972 type->ref = type1.ref;
6973 goto basic_type1;
6974 case TOK_STRUCT:
6975 case TOK_UNION:
6976 struct_decl(&type1, VT_STRUCT);
6977 goto basic_type2;
6978
6979 /* type modifiers */
6980 case TOK_CONST1:
6981 case TOK_CONST2:
6982 case TOK_CONST3:
6983 t |= VT_CONSTANT;
6984 next();
6985 break;
6986 case TOK_VOLATILE1:
6987 case TOK_VOLATILE2:
6988 case TOK_VOLATILE3:
6989 t |= VT_VOLATILE;
6990 next();
6991 break;
6992 case TOK_SIGNED1:
6993 case TOK_SIGNED2:
6994 case TOK_SIGNED3:
6995 typespec_found = 1;
6996 t |= VT_SIGNED;
6997 next();
6998 break;
6999 case TOK_REGISTER:
7000 case TOK_AUTO:
7001 case TOK_RESTRICT1:
7002 case TOK_RESTRICT2:
7003 case TOK_RESTRICT3:
7004 next();
7005 break;
7006 case TOK_UNSIGNED:
7007 t |= VT_UNSIGNED;
7008 next();
7009 typespec_found = 1;
7010 break;
7011
7012 /* storage */
7013 case TOK_EXTERN:
7014 t |= VT_EXTERN;
7015 next();
7016 break;
7017 case TOK_STATIC:
7018 t |= VT_STATIC;
7019 next();
7020 break;
7021 case TOK_TYPEDEF:
7022 t |= VT_TYPEDEF;
7023 next();
7024 break;
7025 case TOK_INLINE1:
7026 case TOK_INLINE2:
7027 case TOK_INLINE3:
7028 t |= VT_INLINE;
7029 next();
7030 break;
7031
7032 /* GNUC attribute */
7033 case TOK_ATTRIBUTE1:
7034 case TOK_ATTRIBUTE2:
7035 parse_attribute(ad);
7036 break;
7037 /* GNUC typeof */
7038 case TOK_TYPEOF1:
7039 case TOK_TYPEOF2:
7040 case TOK_TYPEOF3:
7041 next();
7042 parse_expr_type(&type1);
7043 goto basic_type2;
7044 default:
7045 if (typespec_found || typedef_found)
7046 goto the_end;
7047 s = sym_find(tok);
7048 if (!s || !(s->type.t & VT_TYPEDEF))
7049 goto the_end;
7050 typedef_found = 1;
7051 t |= (s->type.t & ~VT_TYPEDEF);
7052 type->ref = s->type.ref;
7053 next();
7054 typespec_found = 1;
7055 break;
7056 }
7057 type_found = 1;
7058 }
7059 the_end:
7060 if ((t & (VT_SIGNED|VT_UNSIGNED)) == (VT_SIGNED|VT_UNSIGNED))
7061 error("signed and unsigned modifier");
7062 if (tcc_state->char_is_unsigned) {
7063 if ((t & (VT_SIGNED|VT_UNSIGNED|VT_BTYPE)) == VT_BYTE)
7064 t |= VT_UNSIGNED;
7065 }
7066 t &= ~VT_SIGNED;
7067
7068 /* long is never used as type */
7069 if ((t & VT_BTYPE) == VT_LONG)
7070 t = (t & ~VT_BTYPE) | VT_INT;
7071 type->t = t;
7072 return type_found;
7073 }
7074
7075 /* convert a function parameter type (array to pointer and function to
7076 function pointer) */
convert_parameter_type(CType * pt)7077 static inline void convert_parameter_type(CType *pt)
7078 {
7079 /* remove const and volatile qualifiers (XXX: const could be used
7080 to indicate a const function parameter */
7081 pt->t &= ~(VT_CONSTANT | VT_VOLATILE);
7082 /* array must be transformed to pointer according to ANSI C */
7083 pt->t &= ~VT_ARRAY;
7084 if ((pt->t & VT_BTYPE) == VT_FUNC) {
7085 mk_pointer(pt);
7086 }
7087 }
7088
post_type(CType * type,AttributeDef * ad)7089 static void post_type(CType *type, AttributeDef *ad)
7090 {
7091 int n, l, t1, arg_size, align;
7092 Sym **plast, *s, *first;
7093 AttributeDef ad1;
7094 CType pt;
7095
7096 if (tok == '(') {
7097 /* function declaration */
7098 next();
7099 l = 0;
7100 first = NULL;
7101 plast = &first;
7102 arg_size = 0;
7103 if (tok != ')') {
7104 for(;;) {
7105 /* read param name and compute offset */
7106 if (l != FUNC_OLD) {
7107 if (!parse_btype(&pt, &ad1)) {
7108 if (l) {
7109 error("invalid type");
7110 } else {
7111 l = FUNC_OLD;
7112 goto old_proto;
7113 }
7114 }
7115 l = FUNC_NEW;
7116 if ((pt.t & VT_BTYPE) == VT_VOID && tok == ')')
7117 break;
7118 type_decl(&pt, &ad1, &n, TYPE_DIRECT | TYPE_ABSTRACT);
7119 if ((pt.t & VT_BTYPE) == VT_VOID)
7120 error("parameter declared as void");
7121 arg_size += (type_size(&pt, &align) + 3) & ~3;
7122 } else {
7123 old_proto:
7124 n = tok;
7125 if (n < TOK_UIDENT)
7126 expect("identifier");
7127 pt.t = VT_INT;
7128 next();
7129 }
7130 convert_parameter_type(&pt);
7131 s = sym_push(n | SYM_FIELD, &pt, 0, 0);
7132 *plast = s;
7133 plast = &s->next;
7134 if (tok == ')')
7135 break;
7136 skip(',');
7137 if (l == FUNC_NEW && tok == TOK_DOTS) {
7138 l = FUNC_ELLIPSIS;
7139 next();
7140 break;
7141 }
7142 }
7143 }
7144 /* if no parameters, then old type prototype */
7145 if (l == 0)
7146 l = FUNC_OLD;
7147 skip(')');
7148 t1 = type->t & VT_STORAGE;
7149 /* NOTE: const is ignored in returned type as it has a special
7150 meaning in gcc / C++ */
7151 type->t &= ~(VT_STORAGE | VT_CONSTANT);
7152 post_type(type, ad);
7153 /* we push a anonymous symbol which will contain the function prototype */
7154 FUNC_ARGS(ad->func_attr) = arg_size;
7155 s = sym_push(SYM_FIELD, type, ad->func_attr, l);
7156 s->next = first;
7157 type->t = t1 | VT_FUNC;
7158 type->ref = s;
7159 } else if (tok == '[') {
7160 /* array definition */
7161 next();
7162 n = -1;
7163 if (tok != ']') {
7164 n = expr_const();
7165 if (n < 0)
7166 error("invalid array size");
7167 }
7168 skip(']');
7169 /* parse next post type */
7170 t1 = type->t & VT_STORAGE;
7171 type->t &= ~VT_STORAGE;
7172 post_type(type, ad);
7173
7174 /* we push a anonymous symbol which will contain the array
7175 element type */
7176 s = sym_push(SYM_FIELD, type, 0, n);
7177 type->t = t1 | VT_ARRAY | VT_PTR;
7178 type->ref = s;
7179 }
7180 }
7181
7182 /* Parse a type declaration (except basic type), and return the type
7183 in 'type'. 'td' is a bitmask indicating which kind of type decl is
7184 expected. 'type' should contain the basic type. 'ad' is the
7185 attribute definition of the basic type. It can be modified by
7186 type_decl().
7187 */
type_decl(CType * type,AttributeDef * ad,int * v,int td)7188 static void type_decl(CType *type, AttributeDef *ad, int *v, int td)
7189 {
7190 Sym *s;
7191 CType type1, *type2;
7192 int qualifiers;
7193
7194 while (tok == '*') {
7195 qualifiers = 0;
7196 redo:
7197 next();
7198 switch(tok) {
7199 case TOK_CONST1:
7200 case TOK_CONST2:
7201 case TOK_CONST3:
7202 qualifiers |= VT_CONSTANT;
7203 goto redo;
7204 case TOK_VOLATILE1:
7205 case TOK_VOLATILE2:
7206 case TOK_VOLATILE3:
7207 qualifiers |= VT_VOLATILE;
7208 goto redo;
7209 case TOK_RESTRICT1:
7210 case TOK_RESTRICT2:
7211 case TOK_RESTRICT3:
7212 goto redo;
7213 }
7214 mk_pointer(type);
7215 type->t |= qualifiers;
7216 }
7217
7218 /* XXX: clarify attribute handling */
7219 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7220 parse_attribute(ad);
7221
7222 /* recursive type */
7223 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
7224 type1.t = 0; /* XXX: same as int */
7225 if (tok == '(') {
7226 next();
7227 /* XXX: this is not correct to modify 'ad' at this point, but
7228 the syntax is not clear */
7229 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7230 parse_attribute(ad);
7231 type_decl(&type1, ad, v, td);
7232 skip(')');
7233 } else {
7234 /* type identifier */
7235 if (tok >= TOK_IDENT && (td & TYPE_DIRECT)) {
7236 *v = tok;
7237 next();
7238 } else {
7239 if (!(td & TYPE_ABSTRACT))
7240 expect("identifier");
7241 *v = 0;
7242 }
7243 }
7244 post_type(type, ad);
7245 if (tok == TOK_ATTRIBUTE1 || tok == TOK_ATTRIBUTE2)
7246 parse_attribute(ad);
7247 if (!type1.t)
7248 return;
7249 /* append type at the end of type1 */
7250 type2 = &type1;
7251 for(;;) {
7252 s = type2->ref;
7253 type2 = &s->type;
7254 if (!type2->t) {
7255 *type2 = *type;
7256 break;
7257 }
7258 }
7259 *type = type1;
7260 }
7261
7262 /* compute the lvalue VT_LVAL_xxx needed to match type t. */
lvalue_type(int t)7263 static int lvalue_type(int t)
7264 {
7265 int bt, r;
7266 r = VT_LVAL;
7267 bt = t & VT_BTYPE;
7268 if (bt == VT_BYTE || bt == VT_BOOL)
7269 r |= VT_LVAL_BYTE;
7270 else if (bt == VT_SHORT)
7271 r |= VT_LVAL_SHORT;
7272 else
7273 return r;
7274 if (t & VT_UNSIGNED)
7275 r |= VT_LVAL_UNSIGNED;
7276 return r;
7277 }
7278
7279 /* indirection with full error checking and bound check */
indir(void)7280 static void indir(void)
7281 {
7282 if ((vtop->type.t & VT_BTYPE) != VT_PTR) {
7283 if ((vtop->type.t & VT_BTYPE) == VT_FUNC)
7284 return;
7285 expect("pointer");
7286 }
7287 if ((vtop->r & VT_LVAL) && !nocode_wanted)
7288 gv(RC_INT);
7289 vtop->type = *pointed_type(&vtop->type);
7290 /* Arrays and functions are never lvalues */
7291 if (!(vtop->type.t & VT_ARRAY)
7292 && (vtop->type.t & VT_BTYPE) != VT_FUNC) {
7293 vtop->r |= lvalue_type(vtop->type.t);
7294 /* if bound checking, the referenced pointer must be checked */
7295 if (do_bounds_check)
7296 vtop->r |= VT_MUSTBOUND;
7297 }
7298 }
7299
7300 /* pass a parameter to a function and do type checking and casting */
gfunc_param_typed(Sym * func,Sym * arg)7301 static void gfunc_param_typed(Sym *func, Sym *arg)
7302 {
7303 int func_type;
7304 CType type;
7305
7306 func_type = func->c;
7307 if (func_type == FUNC_OLD ||
7308 (func_type == FUNC_ELLIPSIS && arg == NULL)) {
7309 /* default casting : only need to convert float to double */
7310 if ((vtop->type.t & VT_BTYPE) == VT_FLOAT) {
7311 type.t = VT_DOUBLE;
7312 gen_cast(&type);
7313 }
7314 } else if (arg == NULL) {
7315 error("too many arguments to function");
7316 } else {
7317 type = arg->type;
7318 type.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
7319 gen_assign_cast(&type);
7320 }
7321 }
7322
7323 /* parse an expression of the form '(type)' or '(expr)' and return its
7324 type */
parse_expr_type(CType * type)7325 static void parse_expr_type(CType *type)
7326 {
7327 int n;
7328 AttributeDef ad;
7329
7330 skip('(');
7331 if (parse_btype(type, &ad)) {
7332 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7333 } else {
7334 expr_type(type);
7335 }
7336 skip(')');
7337 }
7338
parse_type(CType * type)7339 static void parse_type(CType *type)
7340 {
7341 AttributeDef ad;
7342 int n;
7343
7344 if (!parse_btype(type, &ad)) {
7345 expect("type");
7346 }
7347 type_decl(type, &ad, &n, TYPE_ABSTRACT);
7348 }
7349
vpush_tokc(int t)7350 static void vpush_tokc(int t)
7351 {
7352 CType type;
7353 type.t = t;
7354 vsetc(&type, VT_CONST, &tokc);
7355 }
7356
unary(void)7357 static void unary(void)
7358 {
7359 int n, t, align, size, r;
7360 CType type;
7361 Sym *s;
7362 AttributeDef ad;
7363
7364 /* XXX: GCC 2.95.3 does not generate a table although it should be
7365 better here */
7366 tok_next:
7367 switch(tok) {
7368 case TOK_EXTENSION:
7369 next();
7370 goto tok_next;
7371 case TOK_CINT:
7372 case TOK_CCHAR:
7373 case TOK_LCHAR:
7374 vpushi(tokc.i);
7375 next();
7376 break;
7377 case TOK_CUINT:
7378 vpush_tokc(VT_INT | VT_UNSIGNED);
7379 next();
7380 break;
7381 case TOK_CLLONG:
7382 vpush_tokc(VT_LLONG);
7383 next();
7384 break;
7385 case TOK_CULLONG:
7386 vpush_tokc(VT_LLONG | VT_UNSIGNED);
7387 next();
7388 break;
7389 case TOK_CFLOAT:
7390 vpush_tokc(VT_FLOAT);
7391 next();
7392 break;
7393 case TOK_CDOUBLE:
7394 vpush_tokc(VT_DOUBLE);
7395 next();
7396 break;
7397 case TOK_CLDOUBLE:
7398 vpush_tokc(VT_LDOUBLE);
7399 next();
7400 break;
7401 case TOK___FUNCTION__:
7402 if (!gnu_ext)
7403 goto tok_identifier;
7404 /* fall thru */
7405 case TOK___FUNC__:
7406 {
7407 void *ptr;
7408 int len;
7409 /* special function name identifier */
7410 len = strlen(funcname) + 1;
7411 /* generate char[len] type */
7412 type.t = VT_BYTE;
7413 mk_pointer(&type);
7414 type.t |= VT_ARRAY;
7415 type.ref->c = len;
7416 vpush_ref(&type, data_section, data_section->data_offset, len);
7417 ptr = section_ptr_add(data_section, len);
7418 memcpy(ptr, funcname, len);
7419 next();
7420 }
7421 break;
7422 case TOK_LSTR:
7423 #ifdef TCC_TARGET_PE
7424 t = VT_SHORT | VT_UNSIGNED;
7425 #else
7426 t = VT_INT;
7427 #endif
7428 goto str_init;
7429 case TOK_STR:
7430 /* string parsing */
7431 t = VT_BYTE;
7432 str_init:
7433 if (tcc_state->warn_write_strings)
7434 t |= VT_CONSTANT;
7435 type.t = t;
7436 mk_pointer(&type);
7437 type.t |= VT_ARRAY;
7438 memset(&ad, 0, sizeof(AttributeDef));
7439 decl_initializer_alloc(&type, &ad, VT_CONST, 2, 0, 0);
7440 break;
7441 case '(':
7442 next();
7443 /* cast ? */
7444 if (parse_btype(&type, &ad)) {
7445 type_decl(&type, &ad, &n, TYPE_ABSTRACT);
7446 skip(')');
7447 /* check ISOC99 compound literal */
7448 if (tok == '{') {
7449 /* data is allocated locally by default */
7450 if (global_expr)
7451 r = VT_CONST;
7452 else
7453 r = VT_LOCAL;
7454 /* all except arrays are lvalues */
7455 if (!(type.t & VT_ARRAY))
7456 r |= lvalue_type(type.t);
7457 memset(&ad, 0, sizeof(AttributeDef));
7458 decl_initializer_alloc(&type, &ad, r, 1, 0, 0);
7459 } else {
7460 unary();
7461 gen_cast(&type);
7462 }
7463 } else if (tok == '{') {
7464 /* save all registers */
7465 save_regs(0);
7466 /* statement expression : we do not accept break/continue
7467 inside as GCC does */
7468 block(NULL, NULL, NULL, NULL, 0, 1);
7469 skip(')');
7470 } else {
7471 gexpr();
7472 skip(')');
7473 }
7474 break;
7475 case '*':
7476 next();
7477 unary();
7478 indir();
7479 break;
7480 case '&':
7481 next();
7482 unary();
7483 /* functions names must be treated as function pointers,
7484 except for unary '&' and sizeof. Since we consider that
7485 functions are not lvalues, we only have to handle it
7486 there and in function calls. */
7487 /* arrays can also be used although they are not lvalues */
7488 if ((vtop->type.t & VT_BTYPE) != VT_FUNC &&
7489 !(vtop->type.t & VT_ARRAY) && !(vtop->type.t & VT_LLOCAL))
7490 test_lvalue();
7491 mk_pointer(&vtop->type);
7492 gaddrof();
7493 break;
7494 case '!':
7495 next();
7496 unary();
7497 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST)
7498 vtop->c.i = !vtop->c.i;
7499 else if ((vtop->r & VT_VALMASK) == VT_CMP)
7500 vtop->c.i = vtop->c.i ^ 1;
7501 else {
7502 save_regs(1);
7503 vseti(VT_JMP, gtst(1, 0));
7504 }
7505 break;
7506 case '~':
7507 next();
7508 unary();
7509 vpushi(-1);
7510 gen_op('^');
7511 break;
7512 case '+':
7513 next();
7514 /* in order to force cast, we add zero */
7515 unary();
7516 if ((vtop->type.t & VT_BTYPE) == VT_PTR)
7517 error("pointer not accepted for unary plus");
7518 vpushi(0);
7519 gen_op('+');
7520 break;
7521 case TOK_SIZEOF:
7522 case TOK_ALIGNOF1:
7523 case TOK_ALIGNOF2:
7524 t = tok;
7525 next();
7526 if (tok == '(') {
7527 parse_expr_type(&type);
7528 } else {
7529 unary_type(&type);
7530 }
7531 size = type_size(&type, &align);
7532 if (t == TOK_SIZEOF) {
7533 if (size < 0)
7534 error("sizeof applied to an incomplete type");
7535 vpushi(size);
7536 } else {
7537 vpushi(align);
7538 }
7539 vtop->type.t |= VT_UNSIGNED;
7540 break;
7541
7542 case TOK_builtin_types_compatible_p:
7543 {
7544 CType type1, type2;
7545 next();
7546 skip('(');
7547 parse_type(&type1);
7548 skip(',');
7549 parse_type(&type2);
7550 skip(')');
7551 type1.t &= ~(VT_CONSTANT | VT_VOLATILE);
7552 type2.t &= ~(VT_CONSTANT | VT_VOLATILE);
7553 vpushi(is_compatible_types(&type1, &type2));
7554 }
7555 break;
7556 case TOK_builtin_constant_p:
7557 {
7558 int saved_nocode_wanted, res;
7559 next();
7560 skip('(');
7561 saved_nocode_wanted = nocode_wanted;
7562 nocode_wanted = 1;
7563 gexpr();
7564 res = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
7565 vpop();
7566 nocode_wanted = saved_nocode_wanted;
7567 skip(')');
7568 vpushi(res);
7569 }
7570 break;
7571 case TOK_INC:
7572 case TOK_DEC:
7573 t = tok;
7574 next();
7575 unary();
7576 inc(0, t);
7577 break;
7578 case '-':
7579 next();
7580 vpushi(0);
7581 unary();
7582 gen_op('-');
7583 break;
7584 case TOK_LAND:
7585 if (!gnu_ext)
7586 goto tok_identifier;
7587 next();
7588 /* allow to take the address of a label */
7589 if (tok < TOK_UIDENT)
7590 expect("label identifier");
7591 s = label_find(tok);
7592 if (!s) {
7593 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
7594 } else {
7595 if (s->r == LABEL_DECLARED)
7596 s->r = LABEL_FORWARD;
7597 }
7598 if (!s->type.t) {
7599 s->type.t = VT_VOID;
7600 mk_pointer(&s->type);
7601 s->type.t |= VT_STATIC;
7602 }
7603 vset(&s->type, VT_CONST | VT_SYM, 0);
7604 vtop->sym = s;
7605 next();
7606 break;
7607 default:
7608 tok_identifier:
7609 t = tok;
7610 next();
7611 if (t < TOK_UIDENT)
7612 expect("identifier");
7613 s = sym_find(t);
7614 if (!s) {
7615 if (tok != '(')
7616 error("'%s' undeclared", get_tok_str(t, NULL));
7617 /* for simple function calls, we tolerate undeclared
7618 external reference to int() function */
7619 if (tcc_state->warn_implicit_function_declaration)
7620 warning("implicit declaration of function '%s'",
7621 get_tok_str(t, NULL));
7622 s = external_global_sym(t, &func_old_type, 0);
7623 }
7624 if ((s->type.t & (VT_STATIC | VT_INLINE | VT_BTYPE)) ==
7625 (VT_STATIC | VT_INLINE | VT_FUNC)) {
7626 /* if referencing an inline function, then we generate a
7627 symbol to it if not already done. It will have the
7628 effect to generate code for it at the end of the
7629 compilation unit. Inline function as always
7630 generated in the text section. */
7631 if (!s->c)
7632 put_extern_sym(s, text_section, 0, 0);
7633 r = VT_SYM | VT_CONST;
7634 } else {
7635 r = s->r;
7636 }
7637 vset(&s->type, r, s->c);
7638 /* if forward reference, we must point to s */
7639 if (vtop->r & VT_SYM) {
7640 vtop->sym = s;
7641 vtop->c.ul = 0;
7642 }
7643 break;
7644 }
7645
7646 /* post operations */
7647 while (1) {
7648 if (tok == TOK_INC || tok == TOK_DEC) {
7649 inc(1, tok);
7650 next();
7651 } else if (tok == '.' || tok == TOK_ARROW) {
7652 /* field */
7653 if (tok == TOK_ARROW)
7654 indir();
7655 test_lvalue();
7656 gaddrof();
7657 next();
7658 /* expect pointer on structure */
7659 if ((vtop->type.t & VT_BTYPE) != VT_STRUCT)
7660 expect("struct or union");
7661 s = vtop->type.ref;
7662 /* find field */
7663 tok |= SYM_FIELD;
7664 while ((s = s->next) != NULL) {
7665 if (s->v == tok)
7666 break;
7667 }
7668 if (!s)
7669 error("field not found: %s", get_tok_str(tok & ~SYM_FIELD, NULL));
7670 /* add field offset to pointer */
7671 vtop->type = char_pointer_type; /* change type to 'char *' */
7672 vpushi(s->c);
7673 gen_op('+');
7674 /* change type to field type, and set to lvalue */
7675 vtop->type = s->type;
7676 /* an array is never an lvalue */
7677 if (!(vtop->type.t & VT_ARRAY)) {
7678 vtop->r |= lvalue_type(vtop->type.t);
7679 /* if bound checking, the referenced pointer must be checked */
7680 if (do_bounds_check)
7681 vtop->r |= VT_MUSTBOUND;
7682 }
7683 next();
7684 } else if (tok == '[') {
7685 next();
7686 gexpr();
7687 gen_op('+');
7688 indir();
7689 skip(']');
7690 } else if (tok == '(') {
7691 SValue ret;
7692 Sym *sa;
7693 int nb_args;
7694
7695 /* function call */
7696 if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
7697 /* pointer test (no array accepted) */
7698 if ((vtop->type.t & (VT_BTYPE | VT_ARRAY)) == VT_PTR) {
7699 vtop->type = *pointed_type(&vtop->type);
7700 if ((vtop->type.t & VT_BTYPE) != VT_FUNC)
7701 goto error_func;
7702 } else {
7703 error_func:
7704 expect("function pointer");
7705 }
7706 } else {
7707 vtop->r &= ~VT_LVAL; /* no lvalue */
7708 }
7709 /* get return type */
7710 s = vtop->type.ref;
7711 next();
7712 sa = s->next; /* first parameter */
7713 nb_args = 0;
7714 ret.r2 = VT_CONST;
7715 /* compute first implicit argument if a structure is returned */
7716 if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
7717 /* get some space for the returned structure */
7718 size = type_size(&s->type, &align);
7719 loc = (loc - size) & -align;
7720 ret.type = s->type;
7721 ret.r = VT_LOCAL | VT_LVAL;
7722 /* pass it as 'int' to avoid structure arg passing
7723 problems */
7724 vseti(VT_LOCAL, loc);
7725 ret.c = vtop->c;
7726 nb_args++;
7727 } else {
7728 ret.type = s->type;
7729 /* return in register */
7730 if (is_float(ret.type.t)) {
7731 ret.r = REG_FRET;
7732 } else {
7733 if ((ret.type.t & VT_BTYPE) == VT_LLONG)
7734 ret.r2 = REG_LRET;
7735 ret.r = REG_IRET;
7736 }
7737 ret.c.i = 0;
7738 }
7739 if (tok != ')') {
7740 for(;;) {
7741 expr_eq();
7742 gfunc_param_typed(s, sa);
7743 nb_args++;
7744 if (sa)
7745 sa = sa->next;
7746 if (tok == ')')
7747 break;
7748 skip(',');
7749 }
7750 }
7751 if (sa)
7752 error("too few arguments to function");
7753 skip(')');
7754 if (!nocode_wanted) {
7755 gfunc_call(nb_args);
7756 } else {
7757 vtop -= (nb_args + 1);
7758 }
7759 /* return value */
7760 vsetc(&ret.type, ret.r, &ret.c);
7761 vtop->r2 = ret.r2;
7762 } else {
7763 break;
7764 }
7765 }
7766 }
7767
uneq(void)7768 static void uneq(void)
7769 {
7770 int t;
7771
7772 unary();
7773 if (tok == '=' ||
7774 (tok >= TOK_A_MOD && tok <= TOK_A_DIV) ||
7775 tok == TOK_A_XOR || tok == TOK_A_OR ||
7776 tok == TOK_A_SHL || tok == TOK_A_SAR) {
7777 test_lvalue();
7778 t = tok;
7779 next();
7780 if (t == '=') {
7781 expr_eq();
7782 } else {
7783 vdup();
7784 expr_eq();
7785 gen_op(t & 0x7f);
7786 }
7787 vstore();
7788 }
7789 }
7790
expr_prod(void)7791 static void expr_prod(void)
7792 {
7793 int t;
7794
7795 uneq();
7796 while (tok == '*' || tok == '/' || tok == '%') {
7797 t = tok;
7798 next();
7799 uneq();
7800 gen_op(t);
7801 }
7802 }
7803
expr_sum(void)7804 static void expr_sum(void)
7805 {
7806 int t;
7807
7808 expr_prod();
7809 while (tok == '+' || tok == '-') {
7810 t = tok;
7811 next();
7812 expr_prod();
7813 gen_op(t);
7814 }
7815 }
7816
expr_shift(void)7817 static void expr_shift(void)
7818 {
7819 int t;
7820
7821 expr_sum();
7822 while (tok == TOK_SHL || tok == TOK_SAR) {
7823 t = tok;
7824 next();
7825 expr_sum();
7826 gen_op(t);
7827 }
7828 }
7829
expr_cmp(void)7830 static void expr_cmp(void)
7831 {
7832 int t;
7833
7834 expr_shift();
7835 while ((tok >= TOK_ULE && tok <= TOK_GT) ||
7836 tok == TOK_ULT || tok == TOK_UGE) {
7837 t = tok;
7838 next();
7839 expr_shift();
7840 gen_op(t);
7841 }
7842 }
7843
expr_cmpeq(void)7844 static void expr_cmpeq(void)
7845 {
7846 int t;
7847
7848 expr_cmp();
7849 while (tok == TOK_EQ || tok == TOK_NE) {
7850 t = tok;
7851 next();
7852 expr_cmp();
7853 gen_op(t);
7854 }
7855 }
7856
expr_and(void)7857 static void expr_and(void)
7858 {
7859 expr_cmpeq();
7860 while (tok == '&') {
7861 next();
7862 expr_cmpeq();
7863 gen_op('&');
7864 }
7865 }
7866
expr_xor(void)7867 static void expr_xor(void)
7868 {
7869 expr_and();
7870 while (tok == '^') {
7871 next();
7872 expr_and();
7873 gen_op('^');
7874 }
7875 }
7876
expr_or(void)7877 static void expr_or(void)
7878 {
7879 expr_xor();
7880 while (tok == '|') {
7881 next();
7882 expr_xor();
7883 gen_op('|');
7884 }
7885 }
7886
7887 /* XXX: fix this mess */
expr_land_const(void)7888 static void expr_land_const(void)
7889 {
7890 expr_or();
7891 while (tok == TOK_LAND) {
7892 next();
7893 expr_or();
7894 gen_op(TOK_LAND);
7895 }
7896 }
7897
7898 /* XXX: fix this mess */
expr_lor_const(void)7899 static void expr_lor_const(void)
7900 {
7901 expr_land_const();
7902 while (tok == TOK_LOR) {
7903 next();
7904 expr_land_const();
7905 gen_op(TOK_LOR);
7906 }
7907 }
7908
7909 /* only used if non constant */
expr_land(void)7910 static void expr_land(void)
7911 {
7912 int t;
7913
7914 expr_or();
7915 if (tok == TOK_LAND) {
7916 t = 0;
7917 save_regs(1);
7918 for(;;) {
7919 t = gtst(1, t);
7920 if (tok != TOK_LAND) {
7921 vseti(VT_JMPI, t);
7922 break;
7923 }
7924 next();
7925 expr_or();
7926 }
7927 }
7928 }
7929
expr_lor(void)7930 static void expr_lor(void)
7931 {
7932 int t;
7933
7934 expr_land();
7935 if (tok == TOK_LOR) {
7936 t = 0;
7937 save_regs(1);
7938 for(;;) {
7939 t = gtst(0, t);
7940 if (tok != TOK_LOR) {
7941 vseti(VT_JMP, t);
7942 break;
7943 }
7944 next();
7945 expr_land();
7946 }
7947 }
7948 }
7949
7950 /* XXX: better constant handling */
expr_eq(void)7951 static void expr_eq(void)
7952 {
7953 int tt, u, r1, r2, rc, t1, t2, bt1, bt2;
7954 SValue sv;
7955 CType type, type1, type2;
7956
7957 if (const_wanted) {
7958 int c1, c;
7959 expr_lor_const();
7960 if (tok == '?') {
7961 c = vtop->c.i;
7962 vpop();
7963 next();
7964 if (tok == ':' && gnu_ext) {
7965 c1 = c;
7966 } else {
7967 gexpr();
7968 c1 = vtop->c.i;
7969 vpop();
7970 }
7971 skip(':');
7972 expr_eq();
7973 if (c)
7974 vtop->c.i = c1;
7975 }
7976 } else {
7977 expr_lor();
7978 if (tok == '?') {
7979 next();
7980 if (vtop != vstack) {
7981 /* needed to avoid having different registers saved in
7982 each branch */
7983 if (is_float(vtop->type.t))
7984 rc = RC_FLOAT;
7985 else
7986 rc = RC_INT;
7987 gv(rc);
7988 save_regs(1);
7989 }
7990 if (tok == ':' && gnu_ext) {
7991 gv_dup();
7992 tt = gtst(1, 0);
7993 } else {
7994 tt = gtst(1, 0);
7995 gexpr();
7996 }
7997 type1 = vtop->type;
7998 sv = *vtop; /* save value to handle it later */
7999 vtop--; /* no vpop so that FP stack is not flushed */
8000 skip(':');
8001 u = gjmp(0);
8002 gsym(tt);
8003 expr_eq();
8004 type2 = vtop->type;
8005
8006 t1 = type1.t;
8007 bt1 = t1 & VT_BTYPE;
8008 t2 = type2.t;
8009 bt2 = t2 & VT_BTYPE;
8010 /* cast operands to correct type according to ISOC rules */
8011 if (is_float(bt1) || is_float(bt2)) {
8012 if (bt1 == VT_LDOUBLE || bt2 == VT_LDOUBLE) {
8013 type.t = VT_LDOUBLE;
8014 } else if (bt1 == VT_DOUBLE || bt2 == VT_DOUBLE) {
8015 type.t = VT_DOUBLE;
8016 } else {
8017 type.t = VT_FLOAT;
8018 }
8019 } else if (bt1 == VT_LLONG || bt2 == VT_LLONG) {
8020 /* cast to biggest op */
8021 type.t = VT_LLONG;
8022 /* convert to unsigned if it does not fit in a long long */
8023 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED) ||
8024 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_LLONG | VT_UNSIGNED))
8025 type.t |= VT_UNSIGNED;
8026 } else if (bt1 == VT_PTR || bt2 == VT_PTR) {
8027 /* XXX: test pointer compatibility */
8028 type = type1;
8029 } else if (bt1 == VT_FUNC || bt2 == VT_FUNC) {
8030 /* XXX: test function pointer compatibility */
8031 type = type1;
8032 } else if (bt1 == VT_STRUCT || bt2 == VT_STRUCT) {
8033 /* XXX: test structure compatibility */
8034 type = type1;
8035 } else if (bt1 == VT_VOID || bt2 == VT_VOID) {
8036 /* NOTE: as an extension, we accept void on only one side */
8037 type.t = VT_VOID;
8038 } else {
8039 /* integer operations */
8040 type.t = VT_INT;
8041 /* convert to unsigned if it does not fit in an integer */
8042 if ((t1 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED) ||
8043 (t2 & (VT_BTYPE | VT_UNSIGNED)) == (VT_INT | VT_UNSIGNED))
8044 type.t |= VT_UNSIGNED;
8045 }
8046
8047 /* now we convert second operand */
8048 gen_cast(&type);
8049 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8050 gaddrof();
8051 rc = RC_INT;
8052 if (is_float(type.t)) {
8053 rc = RC_FLOAT;
8054 } else if ((type.t & VT_BTYPE) == VT_LLONG) {
8055 /* for long longs, we use fixed registers to avoid having
8056 to handle a complicated move */
8057 rc = RC_IRET;
8058 }
8059
8060 r2 = gv(rc);
8061 /* this is horrible, but we must also convert first
8062 operand */
8063 tt = gjmp(0);
8064 gsym(u);
8065 /* put again first value and cast it */
8066 *vtop = sv;
8067 gen_cast(&type);
8068 if (VT_STRUCT == (vtop->type.t & VT_BTYPE))
8069 gaddrof();
8070 r1 = gv(rc);
8071 move_reg(r2, r1);
8072 vtop->r = r2;
8073 gsym(tt);
8074 }
8075 }
8076 }
8077
gexpr(void)8078 static void gexpr(void)
8079 {
8080 while (1) {
8081 expr_eq();
8082 if (tok != ',')
8083 break;
8084 vpop();
8085 next();
8086 }
8087 }
8088
8089 /* parse an expression and return its type without any side effect. */
expr_type(CType * type)8090 static void expr_type(CType *type)
8091 {
8092 int saved_nocode_wanted;
8093
8094 saved_nocode_wanted = nocode_wanted;
8095 nocode_wanted = 1;
8096 gexpr();
8097 *type = vtop->type;
8098 vpop();
8099 nocode_wanted = saved_nocode_wanted;
8100 }
8101
8102 /* parse a unary expression and return its type without any side
8103 effect. */
unary_type(CType * type)8104 static void unary_type(CType *type)
8105 {
8106 int a;
8107
8108 a = nocode_wanted;
8109 nocode_wanted = 1;
8110 unary();
8111 *type = vtop->type;
8112 vpop();
8113 nocode_wanted = a;
8114 }
8115
8116 /* parse a constant expression and return value in vtop. */
expr_const1(void)8117 static void expr_const1(void)
8118 {
8119 int a;
8120 a = const_wanted;
8121 const_wanted = 1;
8122 expr_eq();
8123 const_wanted = a;
8124 }
8125
8126 /* parse an integer constant and return its value. */
expr_const(void)8127 static int expr_const(void)
8128 {
8129 int c;
8130 expr_const1();
8131 if ((vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) != VT_CONST)
8132 expect("constant expression");
8133 c = vtop->c.i;
8134 vpop();
8135 return c;
8136 }
8137
8138 /* return the label token if current token is a label, otherwise
8139 return zero */
is_label(void)8140 static int is_label(void)
8141 {
8142 int last_tok;
8143
8144 /* fast test first */
8145 if (tok < TOK_UIDENT)
8146 return 0;
8147 /* no need to save tokc because tok is an identifier */
8148 last_tok = tok;
8149 next();
8150 if (tok == ':') {
8151 next();
8152 return last_tok;
8153 } else {
8154 unget_tok(last_tok);
8155 return 0;
8156 }
8157 }
8158
block(int * bsym,int * csym,int * case_sym,int * def_sym,int case_reg,int is_expr)8159 static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
8160 int case_reg, int is_expr)
8161 {
8162 int a, b, c, d;
8163 Sym *s;
8164
8165 /* generate line number info */
8166 if (do_debug &&
8167 (last_line_num != file->line_num || last_ind != ind)) {
8168 put_stabn(N_SLINE, 0, file->line_num, ind - func_ind);
8169 last_ind = ind;
8170 last_line_num = file->line_num;
8171 }
8172
8173 if (is_expr) {
8174 /* default return value is (void) */
8175 vpushi(0);
8176 vtop->type.t = VT_VOID;
8177 }
8178
8179 if (tok == TOK_IF) {
8180 /* if test */
8181 next();
8182 skip('(');
8183 gexpr();
8184 skip(')');
8185 a = gtst(1, 0);
8186 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8187 c = tok;
8188 if (c == TOK_ELSE) {
8189 next();
8190 d = gjmp(0);
8191 gsym(a);
8192 block(bsym, csym, case_sym, def_sym, case_reg, 0);
8193 gsym(d); /* patch else jmp */
8194 } else
8195 gsym(a);
8196 } else if (tok == TOK_WHILE) {
8197 next();
8198 d = ind;
8199 skip('(');
8200 gexpr();
8201 skip(')');
8202 a = gtst(1, 0);
8203 b = 0;
8204 block(&a, &b, case_sym, def_sym, case_reg, 0);
8205 gjmp_addr(d);
8206 gsym(a);
8207 gsym_addr(b, d);
8208 } else if (tok == '{') {
8209 Sym *llabel;
8210
8211 next();
8212 /* record local declaration stack position */
8213 s = local_stack;
8214 llabel = local_label_stack;
8215 /* handle local labels declarations */
8216 if (tok == TOK_LABEL) {
8217 next();
8218 for(;;) {
8219 if (tok < TOK_UIDENT)
8220 expect("label identifier");
8221 label_push(&local_label_stack, tok, LABEL_DECLARED);
8222 next();
8223 if (tok == ',') {
8224 next();
8225 } else {
8226 skip(';');
8227 break;
8228 }
8229 }
8230 }
8231 while (tok != '}') {
8232 decl(VT_LOCAL);
8233 if (tok != '}') {
8234 if (is_expr)
8235 vpop();
8236 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8237 }
8238 }
8239 /* pop locally defined labels */
8240 label_pop(&local_label_stack, llabel);
8241 /* pop locally defined symbols */
8242 sym_pop(&local_stack, s);
8243 next();
8244 } else if (tok == TOK_RETURN) {
8245 next();
8246 if (tok != ';') {
8247 gexpr();
8248 gen_assign_cast(&func_vt);
8249 if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
8250 CType type;
8251 /* if returning structure, must copy it to implicit
8252 first pointer arg location */
8253 #ifdef TCC_ARM_EABI
8254 int align, size;
8255 size = type_size(&func_vt,&align);
8256 if(size <= 4)
8257 {
8258 if((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & 3))
8259 && (align & 3))
8260 {
8261 int addr;
8262 loc = (loc - size) & -4;
8263 addr = loc;
8264 type = func_vt;
8265 vset(&type, VT_LOCAL | VT_LVAL, addr);
8266 vswap();
8267 vstore();
8268 vset(&int_type, VT_LOCAL | VT_LVAL, addr);
8269 }
8270 vtop->type = int_type;
8271 gv(RC_IRET);
8272 } else {
8273 #endif
8274 type = func_vt;
8275 mk_pointer(&type);
8276 vset(&type, VT_LOCAL | VT_LVAL, func_vc);
8277 indir();
8278 vswap();
8279 /* copy structure value to pointer */
8280 vstore();
8281 #ifdef TCC_ARM_EABI
8282 }
8283 #endif
8284 } else if (is_float(func_vt.t)) {
8285 gv(RC_FRET);
8286 } else {
8287 gv(RC_IRET);
8288 }
8289 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
8290 }
8291 skip(';');
8292 rsym = gjmp(rsym); /* jmp */
8293 } else if (tok == TOK_BREAK) {
8294 /* compute jump */
8295 if (!bsym)
8296 error("cannot break");
8297 *bsym = gjmp(*bsym);
8298 next();
8299 skip(';');
8300 } else if (tok == TOK_CONTINUE) {
8301 /* compute jump */
8302 if (!csym)
8303 error("cannot continue");
8304 *csym = gjmp(*csym);
8305 next();
8306 skip(';');
8307 } else if (tok == TOK_FOR) {
8308 int e;
8309 next();
8310 skip('(');
8311 if (tok != ';') {
8312 gexpr();
8313 vpop();
8314 }
8315 skip(';');
8316 d = ind;
8317 c = ind;
8318 a = 0;
8319 b = 0;
8320 if (tok != ';') {
8321 gexpr();
8322 a = gtst(1, 0);
8323 }
8324 skip(';');
8325 if (tok != ')') {
8326 e = gjmp(0);
8327 c = ind;
8328 gexpr();
8329 vpop();
8330 gjmp_addr(d);
8331 gsym(e);
8332 }
8333 skip(')');
8334 block(&a, &b, case_sym, def_sym, case_reg, 0);
8335 gjmp_addr(c);
8336 gsym(a);
8337 gsym_addr(b, c);
8338 } else
8339 if (tok == TOK_DO) {
8340 next();
8341 a = 0;
8342 b = 0;
8343 d = ind;
8344 block(&a, &b, case_sym, def_sym, case_reg, 0);
8345 skip(TOK_WHILE);
8346 skip('(');
8347 gsym(b);
8348 gexpr();
8349 c = gtst(0, 0);
8350 gsym_addr(c, d);
8351 skip(')');
8352 gsym(a);
8353 skip(';');
8354 } else
8355 if (tok == TOK_SWITCH) {
8356 next();
8357 skip('(');
8358 gexpr();
8359 /* XXX: other types than integer */
8360 case_reg = gv(RC_INT);
8361 vpop();
8362 skip(')');
8363 a = 0;
8364 b = gjmp(0); /* jump to first case */
8365 c = 0;
8366 block(&a, csym, &b, &c, case_reg, 0);
8367 /* if no default, jmp after switch */
8368 if (c == 0)
8369 c = ind;
8370 /* default label */
8371 gsym_addr(b, c);
8372 /* break label */
8373 gsym(a);
8374 } else
8375 if (tok == TOK_CASE) {
8376 int v1, v2;
8377 if (!case_sym)
8378 expect("switch");
8379 next();
8380 v1 = expr_const();
8381 v2 = v1;
8382 if (gnu_ext && tok == TOK_DOTS) {
8383 next();
8384 v2 = expr_const();
8385 if (v2 < v1)
8386 warning("empty case range");
8387 }
8388 /* since a case is like a label, we must skip it with a jmp */
8389 b = gjmp(0);
8390 gsym(*case_sym);
8391 vseti(case_reg, 0);
8392 vpushi(v1);
8393 if (v1 == v2) {
8394 gen_op(TOK_EQ);
8395 *case_sym = gtst(1, 0);
8396 } else {
8397 gen_op(TOK_GE);
8398 *case_sym = gtst(1, 0);
8399 vseti(case_reg, 0);
8400 vpushi(v2);
8401 gen_op(TOK_LE);
8402 *case_sym = gtst(1, *case_sym);
8403 }
8404 gsym(b);
8405 skip(':');
8406 is_expr = 0;
8407 goto block_after_label;
8408 } else
8409 if (tok == TOK_DEFAULT) {
8410 next();
8411 skip(':');
8412 if (!def_sym)
8413 expect("switch");
8414 if (*def_sym)
8415 error("too many 'default'");
8416 *def_sym = ind;
8417 is_expr = 0;
8418 goto block_after_label;
8419 } else
8420 if (tok == TOK_GOTO) {
8421 next();
8422 if (tok == '*' && gnu_ext) {
8423 /* computed goto */
8424 next();
8425 gexpr();
8426 if ((vtop->type.t & VT_BTYPE) != VT_PTR)
8427 expect("pointer");
8428 ggoto();
8429 } else if (tok >= TOK_UIDENT) {
8430 s = label_find(tok);
8431 /* put forward definition if needed */
8432 if (!s) {
8433 s = label_push(&global_label_stack, tok, LABEL_FORWARD);
8434 } else {
8435 if (s->r == LABEL_DECLARED)
8436 s->r = LABEL_FORWARD;
8437 }
8438 /* label already defined */
8439 if (s->r & LABEL_FORWARD)
8440 s->next = (void *)gjmp((long)s->next);
8441 else
8442 gjmp_addr((long)s->next);
8443 next();
8444 } else {
8445 expect("label identifier");
8446 }
8447 skip(';');
8448 } else if (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3) {
8449 asm_instr();
8450 } else {
8451 b = is_label();
8452 if (b) {
8453 /* label case */
8454 s = label_find(b);
8455 if (s) {
8456 if (s->r == LABEL_DEFINED)
8457 error("duplicate label '%s'", get_tok_str(s->v, NULL));
8458 gsym((long)s->next);
8459 s->r = LABEL_DEFINED;
8460 } else {
8461 s = label_push(&global_label_stack, b, LABEL_DEFINED);
8462 }
8463 s->next = (void *)ind;
8464 /* we accept this, but it is a mistake */
8465 block_after_label:
8466 if (tok == '}') {
8467 warning("deprecated use of label at end of compound statement");
8468 } else {
8469 if (is_expr)
8470 vpop();
8471 block(bsym, csym, case_sym, def_sym, case_reg, is_expr);
8472 }
8473 } else {
8474 /* expression case */
8475 if (tok != ';') {
8476 if (is_expr) {
8477 vpop();
8478 gexpr();
8479 } else {
8480 gexpr();
8481 vpop();
8482 }
8483 }
8484 skip(';');
8485 }
8486 }
8487 }
8488
8489 /* t is the array or struct type. c is the array or struct
8490 address. cur_index/cur_field is the pointer to the current
8491 value. 'size_only' is true if only size info is needed (only used
8492 in arrays) */
decl_designator(CType * type,Section * sec,unsigned long c,int * cur_index,Sym ** cur_field,int size_only)8493 static void decl_designator(CType *type, Section *sec, unsigned long c,
8494 int *cur_index, Sym **cur_field,
8495 int size_only)
8496 {
8497 Sym *s, *f;
8498 int notfirst, index, index_last, align, l, nb_elems, elem_size;
8499 CType type1;
8500
8501 notfirst = 0;
8502 elem_size = 0;
8503 nb_elems = 1;
8504 if (gnu_ext && (l = is_label()) != 0)
8505 goto struct_field;
8506 while (tok == '[' || tok == '.') {
8507 if (tok == '[') {
8508 if (!(type->t & VT_ARRAY))
8509 expect("array type");
8510 s = type->ref;
8511 next();
8512 index = expr_const();
8513 if (index < 0 || (s->c >= 0 && index >= s->c))
8514 expect("invalid index");
8515 if (tok == TOK_DOTS && gnu_ext) {
8516 next();
8517 index_last = expr_const();
8518 if (index_last < 0 ||
8519 (s->c >= 0 && index_last >= s->c) ||
8520 index_last < index)
8521 expect("invalid index");
8522 } else {
8523 index_last = index;
8524 }
8525 skip(']');
8526 if (!notfirst)
8527 *cur_index = index_last;
8528 type = pointed_type(type);
8529 elem_size = type_size(type, &align);
8530 c += index * elem_size;
8531 /* NOTE: we only support ranges for last designator */
8532 nb_elems = index_last - index + 1;
8533 if (nb_elems != 1) {
8534 notfirst = 1;
8535 break;
8536 }
8537 } else {
8538 next();
8539 l = tok;
8540 next();
8541 struct_field:
8542 if ((type->t & VT_BTYPE) != VT_STRUCT)
8543 expect("struct/union type");
8544 s = type->ref;
8545 l |= SYM_FIELD;
8546 f = s->next;
8547 while (f) {
8548 if (f->v == l)
8549 break;
8550 f = f->next;
8551 }
8552 if (!f)
8553 expect("field");
8554 if (!notfirst)
8555 *cur_field = f;
8556 /* XXX: fix this mess by using explicit storage field */
8557 type1 = f->type;
8558 type1.t |= (type->t & ~VT_TYPE);
8559 type = &type1;
8560 c += f->c;
8561 }
8562 notfirst = 1;
8563 }
8564 if (notfirst) {
8565 if (tok == '=') {
8566 next();
8567 } else {
8568 if (!gnu_ext)
8569 expect("=");
8570 }
8571 } else {
8572 if (type->t & VT_ARRAY) {
8573 index = *cur_index;
8574 type = pointed_type(type);
8575 c += index * type_size(type, &align);
8576 } else {
8577 f = *cur_field;
8578 if (!f)
8579 error("too many field init");
8580 /* XXX: fix this mess by using explicit storage field */
8581 type1 = f->type;
8582 type1.t |= (type->t & ~VT_TYPE);
8583 type = &type1;
8584 c += f->c;
8585 }
8586 }
8587 decl_initializer(type, sec, c, 0, size_only);
8588
8589 /* XXX: make it more general */
8590 if (!size_only && nb_elems > 1) {
8591 unsigned long c_end;
8592 uint8_t *src, *dst;
8593 int i;
8594
8595 if (!sec)
8596 error("range init not supported yet for dynamic storage");
8597 c_end = c + nb_elems * elem_size;
8598 if (c_end > sec->data_allocated)
8599 section_realloc(sec, c_end);
8600 src = sec->data + c;
8601 dst = src;
8602 for(i = 1; i < nb_elems; i++) {
8603 dst += elem_size;
8604 memcpy(dst, src, elem_size);
8605 }
8606 }
8607 }
8608
8609 #define EXPR_VAL 0
8610 #define EXPR_CONST 1
8611 #define EXPR_ANY 2
8612
8613 /* store a value or an expression directly in global data or in local array */
init_putv(CType * type,Section * sec,unsigned long c,int v,int expr_type)8614 static void init_putv(CType *type, Section *sec, unsigned long c,
8615 int v, int expr_type)
8616 {
8617 int saved_global_expr, bt, bit_pos, bit_size;
8618 void *ptr;
8619 unsigned long long bit_mask;
8620 CType dtype;
8621
8622 switch(expr_type) {
8623 case EXPR_VAL:
8624 vpushi(v);
8625 break;
8626 case EXPR_CONST:
8627 /* compound literals must be allocated globally in this case */
8628 saved_global_expr = global_expr;
8629 global_expr = 1;
8630 expr_const1();
8631 global_expr = saved_global_expr;
8632 /* NOTE: symbols are accepted */
8633 if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
8634 error("initializer element is not constant");
8635 break;
8636 case EXPR_ANY:
8637 expr_eq();
8638 break;
8639 }
8640
8641 dtype = *type;
8642 dtype.t &= ~VT_CONSTANT; /* need to do that to avoid false warning */
8643
8644 if (sec) {
8645 /* XXX: not portable */
8646 /* XXX: generate error if incorrect relocation */
8647 gen_assign_cast(&dtype);
8648 bt = type->t & VT_BTYPE;
8649 ptr = sec->data + c;
8650 /* XXX: make code faster ? */
8651 if (!(type->t & VT_BITFIELD)) {
8652 bit_pos = 0;
8653 bit_size = 32;
8654 bit_mask = -1LL;
8655 } else {
8656 bit_pos = (vtop->type.t >> VT_STRUCT_SHIFT) & 0x3f;
8657 bit_size = (vtop->type.t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
8658 bit_mask = (1LL << bit_size) - 1;
8659 }
8660 if ((vtop->r & VT_SYM) &&
8661 (bt == VT_BYTE ||
8662 bt == VT_SHORT ||
8663 bt == VT_DOUBLE ||
8664 bt == VT_LDOUBLE ||
8665 bt == VT_LLONG ||
8666 (bt == VT_INT && bit_size != 32)))
8667 error("initializer element is not computable at load time");
8668 switch(bt) {
8669 case VT_BYTE:
8670 *(char *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8671 break;
8672 case VT_SHORT:
8673 *(short *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8674 break;
8675 case VT_DOUBLE:
8676 *(double *)ptr = vtop->c.d;
8677 break;
8678 case VT_LDOUBLE:
8679 *(long double *)ptr = vtop->c.ld;
8680 break;
8681 case VT_LLONG:
8682 *(long long *)ptr |= (vtop->c.ll & bit_mask) << bit_pos;
8683 break;
8684 default:
8685 if (vtop->r & VT_SYM) {
8686 greloc(sec, vtop->sym, c, R_DATA_32);
8687 }
8688 *(int *)ptr |= (vtop->c.i & bit_mask) << bit_pos;
8689 break;
8690 }
8691 vtop--;
8692 } else {
8693 vset(&dtype, VT_LOCAL|VT_LVAL, c);
8694 vswap();
8695 vstore();
8696 vpop();
8697 }
8698 }
8699
8700 /* put zeros for variable based init */
init_putz(CType * t,Section * sec,unsigned long c,int size)8701 static void init_putz(CType *t, Section *sec, unsigned long c, int size)
8702 {
8703 if (sec) {
8704 /* nothing to do because globals are already set to zero */
8705 } else {
8706 vpush_global_sym(&func_old_type, TOK_memset);
8707 vseti(VT_LOCAL, c);
8708 vpushi(0);
8709 vpushi(size);
8710 gfunc_call(3);
8711 }
8712 }
8713
8714 /* 't' contains the type and storage info. 'c' is the offset of the
8715 object in section 'sec'. If 'sec' is NULL, it means stack based
8716 allocation. 'first' is true if array '{' must be read (multi
8717 dimension implicit array init handling). 'size_only' is true if
8718 size only evaluation is wanted (only for arrays). */
decl_initializer(CType * type,Section * sec,unsigned long c,int first,int size_only)8719 static void decl_initializer(CType *type, Section *sec, unsigned long c,
8720 int first, int size_only)
8721 {
8722 int index, array_length, n, no_oblock, nb, parlevel, i;
8723 int size1, align1, expr_type;
8724 Sym *s, *f;
8725 CType *t1;
8726
8727 if (type->t & VT_ARRAY) {
8728 s = type->ref;
8729 n = s->c;
8730 array_length = 0;
8731 t1 = pointed_type(type);
8732 size1 = type_size(t1, &align1);
8733
8734 no_oblock = 1;
8735 if ((first && tok != TOK_LSTR && tok != TOK_STR) ||
8736 tok == '{') {
8737 skip('{');
8738 no_oblock = 0;
8739 }
8740
8741 /* only parse strings here if correct type (otherwise: handle
8742 them as ((w)char *) expressions */
8743 if ((tok == TOK_LSTR &&
8744 #ifdef TCC_TARGET_PE
8745 (t1->t & VT_BTYPE) == VT_SHORT && (t1->t & VT_UNSIGNED)
8746 #else
8747 (t1->t & VT_BTYPE) == VT_INT
8748 #endif
8749 ) || (tok == TOK_STR && (t1->t & VT_BTYPE) == VT_BYTE)) {
8750 while (tok == TOK_STR || tok == TOK_LSTR) {
8751 int cstr_len, ch;
8752 CString *cstr;
8753
8754 cstr = tokc.cstr;
8755 /* compute maximum number of chars wanted */
8756 if (tok == TOK_STR)
8757 cstr_len = cstr->size;
8758 else
8759 cstr_len = cstr->size / sizeof(nwchar_t);
8760 cstr_len--;
8761 nb = cstr_len;
8762 if (n >= 0 && nb > (n - array_length))
8763 nb = n - array_length;
8764 if (!size_only) {
8765 if (cstr_len > nb)
8766 warning("initializer-string for array is too long");
8767 /* in order to go faster for common case (char
8768 string in global variable, we handle it
8769 specifically */
8770 if (sec && tok == TOK_STR && size1 == 1) {
8771 memcpy(sec->data + c + array_length, cstr->data, nb);
8772 } else {
8773 for(i=0;i<nb;i++) {
8774 if (tok == TOK_STR)
8775 ch = ((unsigned char *)cstr->data)[i];
8776 else
8777 ch = ((nwchar_t *)cstr->data)[i];
8778 init_putv(t1, sec, c + (array_length + i) * size1,
8779 ch, EXPR_VAL);
8780 }
8781 }
8782 }
8783 array_length += nb;
8784 next();
8785 }
8786 /* only add trailing zero if enough storage (no
8787 warning in this case since it is standard) */
8788 if (n < 0 || array_length < n) {
8789 if (!size_only) {
8790 init_putv(t1, sec, c + (array_length * size1), 0, EXPR_VAL);
8791 }
8792 array_length++;
8793 }
8794 } else {
8795 index = 0;
8796 while (tok != '}') {
8797 decl_designator(type, sec, c, &index, NULL, size_only);
8798 if (n >= 0 && index >= n)
8799 error("index too large");
8800 /* must put zero in holes (note that doing it that way
8801 ensures that it even works with designators) */
8802 if (!size_only && array_length < index) {
8803 init_putz(t1, sec, c + array_length * size1,
8804 (index - array_length) * size1);
8805 }
8806 index++;
8807 if (index > array_length)
8808 array_length = index;
8809 /* special test for multi dimensional arrays (may not
8810 be strictly correct if designators are used at the
8811 same time) */
8812 if (index >= n && no_oblock)
8813 break;
8814 if (tok == '}')
8815 break;
8816 skip(',');
8817 }
8818 }
8819 if (!no_oblock)
8820 skip('}');
8821 /* put zeros at the end */
8822 if (!size_only && n >= 0 && array_length < n) {
8823 init_putz(t1, sec, c + array_length * size1,
8824 (n - array_length) * size1);
8825 }
8826 /* patch type size if needed */
8827 if (n < 0)
8828 s->c = array_length;
8829 } else if ((type->t & VT_BTYPE) == VT_STRUCT &&
8830 (sec || !first || tok == '{')) {
8831 int par_count;
8832
8833 /* NOTE: the previous test is a specific case for automatic
8834 struct/union init */
8835 /* XXX: union needs only one init */
8836
8837 /* XXX: this test is incorrect for local initializers
8838 beginning with ( without {. It would be much more difficult
8839 to do it correctly (ideally, the expression parser should
8840 be used in all cases) */
8841 par_count = 0;
8842 if (tok == '(') {
8843 AttributeDef ad1;
8844 CType type1;
8845 next();
8846 while (tok == '(') {
8847 par_count++;
8848 next();
8849 }
8850 if (!parse_btype(&type1, &ad1))
8851 expect("cast");
8852 type_decl(&type1, &ad1, &n, TYPE_ABSTRACT);
8853 #if 0
8854 if (!is_assignable_types(type, &type1))
8855 error("invalid type for cast");
8856 #endif
8857 skip(')');
8858 }
8859 no_oblock = 1;
8860 if (first || tok == '{') {
8861 skip('{');
8862 no_oblock = 0;
8863 }
8864 s = type->ref;
8865 f = s->next;
8866 array_length = 0;
8867 index = 0;
8868 n = s->c;
8869 while (tok != '}') {
8870 decl_designator(type, sec, c, NULL, &f, size_only);
8871 index = f->c;
8872 if (!size_only && array_length < index) {
8873 init_putz(type, sec, c + array_length,
8874 index - array_length);
8875 }
8876 index = index + type_size(&f->type, &align1);
8877 if (index > array_length)
8878 array_length = index;
8879 f = f->next;
8880 if (no_oblock && f == NULL)
8881 break;
8882 if (tok == '}')
8883 break;
8884 skip(',');
8885 }
8886 /* put zeros at the end */
8887 if (!size_only && array_length < n) {
8888 init_putz(type, sec, c + array_length,
8889 n - array_length);
8890 }
8891 if (!no_oblock)
8892 skip('}');
8893 while (par_count) {
8894 skip(')');
8895 par_count--;
8896 }
8897 } else if (tok == '{') {
8898 next();
8899 decl_initializer(type, sec, c, first, size_only);
8900 skip('}');
8901 } else if (size_only) {
8902 /* just skip expression */
8903 parlevel = 0;
8904 while ((parlevel > 0 || (tok != '}' && tok != ',')) &&
8905 tok != -1) {
8906 if (tok == '(')
8907 parlevel++;
8908 else if (tok == ')')
8909 parlevel--;
8910 next();
8911 }
8912 } else {
8913 /* currently, we always use constant expression for globals
8914 (may change for scripting case) */
8915 expr_type = EXPR_CONST;
8916 if (!sec)
8917 expr_type = EXPR_ANY;
8918 init_putv(type, sec, c, 0, expr_type);
8919 }
8920 }
8921
8922 /* parse an initializer for type 't' if 'has_init' is non zero, and
8923 allocate space in local or global data space ('r' is either
8924 VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated
8925 variable 'v' of scope 'scope' is declared before initializers are
8926 parsed. If 'v' is zero, then a reference to the new object is put
8927 in the value stack. If 'has_init' is 2, a special parsing is done
8928 to handle string constants. */
decl_initializer_alloc(CType * type,AttributeDef * ad,int r,int has_init,int v,int scope)8929 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r,
8930 int has_init, int v, int scope)
8931 {
8932 int size, align, addr, data_offset;
8933 int level;
8934 ParseState saved_parse_state;
8935 TokenString init_str;
8936 Section *sec;
8937
8938 size = type_size(type, &align);
8939 /* If unknown size, we must evaluate it before
8940 evaluating initializers because
8941 initializers can generate global data too
8942 (e.g. string pointers or ISOC99 compound
8943 literals). It also simplifies local
8944 initializers handling */
8945 tok_str_new(&init_str);
8946 if (size < 0) {
8947 if (!has_init)
8948 error("unknown type size");
8949 /* get all init string */
8950 if (has_init == 2) {
8951 /* only get strings */
8952 while (tok == TOK_STR || tok == TOK_LSTR) {
8953 tok_str_add_tok(&init_str);
8954 next();
8955 }
8956 } else {
8957 level = 0;
8958 while (level > 0 || (tok != ',' && tok != ';')) {
8959 if (tok < 0)
8960 error("unexpected end of file in initializer");
8961 tok_str_add_tok(&init_str);
8962 if (tok == '{')
8963 level++;
8964 else if (tok == '}') {
8965 if (level == 0)
8966 break;
8967 level--;
8968 }
8969 next();
8970 }
8971 }
8972 tok_str_add(&init_str, -1);
8973 tok_str_add(&init_str, 0);
8974
8975 /* compute size */
8976 save_parse_state(&saved_parse_state);
8977
8978 macro_ptr = init_str.str;
8979 next();
8980 decl_initializer(type, NULL, 0, 1, 1);
8981 /* prepare second initializer parsing */
8982 macro_ptr = init_str.str;
8983 next();
8984
8985 /* if still unknown size, error */
8986 size = type_size(type, &align);
8987 if (size < 0)
8988 error("unknown type size");
8989 }
8990 /* take into account specified alignment if bigger */
8991 if (ad->aligned) {
8992 if (ad->aligned > align)
8993 align = ad->aligned;
8994 } else if (ad->packed) {
8995 align = 1;
8996 }
8997 if ((r & VT_VALMASK) == VT_LOCAL) {
8998 sec = NULL;
8999 if (do_bounds_check && (type->t & VT_ARRAY))
9000 loc--;
9001 loc = (loc - size) & -align;
9002 addr = loc;
9003 /* handles bounds */
9004 /* XXX: currently, since we do only one pass, we cannot track
9005 '&' operators, so we add only arrays */
9006 if (do_bounds_check && (type->t & VT_ARRAY)) {
9007 unsigned long *bounds_ptr;
9008 /* add padding between regions */
9009 loc--;
9010 /* then add local bound info */
9011 bounds_ptr = section_ptr_add(lbounds_section, 2 * sizeof(unsigned long));
9012 bounds_ptr[0] = addr;
9013 bounds_ptr[1] = size;
9014 }
9015 if (v) {
9016 /* local variable */
9017 sym_push(v, type, r, addr);
9018 } else {
9019 /* push local reference */
9020 vset(type, r, addr);
9021 }
9022 } else {
9023 Sym *sym;
9024
9025 sym = NULL;
9026 if (v && scope == VT_CONST) {
9027 /* see if the symbol was already defined */
9028 sym = sym_find(v);
9029 if (sym) {
9030 if (!is_compatible_types(&sym->type, type))
9031 error("incompatible types for redefinition of '%s'",
9032 get_tok_str(v, NULL));
9033 if (sym->type.t & VT_EXTERN) {
9034 /* if the variable is extern, it was not allocated */
9035 sym->type.t &= ~VT_EXTERN;
9036 /* set array size if it was ommited in extern
9037 declaration */
9038 if ((sym->type.t & VT_ARRAY) &&
9039 sym->type.ref->c < 0 &&
9040 type->ref->c >= 0)
9041 sym->type.ref->c = type->ref->c;
9042 } else {
9043 /* we accept several definitions of the same
9044 global variable. this is tricky, because we
9045 must play with the SHN_COMMON type of the symbol */
9046 /* XXX: should check if the variable was already
9047 initialized. It is incorrect to initialized it
9048 twice */
9049 /* no init data, we won't add more to the symbol */
9050 if (!has_init)
9051 goto no_alloc;
9052 }
9053 }
9054 }
9055
9056 /* allocate symbol in corresponding section */
9057 sec = ad->section;
9058 if (!sec) {
9059 if (has_init)
9060 sec = data_section;
9061 else if (tcc_state->nocommon)
9062 sec = bss_section;
9063 }
9064 if (sec) {
9065 data_offset = sec->data_offset;
9066 data_offset = (data_offset + align - 1) & -align;
9067 addr = data_offset;
9068 /* very important to increment global pointer at this time
9069 because initializers themselves can create new initializers */
9070 data_offset += size;
9071 /* add padding if bound check */
9072 if (do_bounds_check)
9073 data_offset++;
9074 sec->data_offset = data_offset;
9075 /* allocate section space to put the data */
9076 if (sec->sh_type != SHT_NOBITS &&
9077 data_offset > sec->data_allocated)
9078 section_realloc(sec, data_offset);
9079 /* align section if needed */
9080 if (align > sec->sh_addralign)
9081 sec->sh_addralign = align;
9082 } else {
9083 addr = 0; /* avoid warning */
9084 }
9085
9086 if (v) {
9087 if (scope != VT_CONST || !sym) {
9088 sym = sym_push(v, type, r | VT_SYM, 0);
9089 }
9090 /* update symbol definition */
9091 if (sec) {
9092 put_extern_sym(sym, sec, addr, size);
9093 } else {
9094 Elf32_Sym *esym;
9095 /* put a common area */
9096 put_extern_sym(sym, NULL, align, size);
9097 /* XXX: find a nicer way */
9098 esym = &((Elf32_Sym *)symtab_section->data)[sym->c];
9099 esym->st_shndx = SHN_COMMON;
9100 }
9101 } else {
9102 CValue cval;
9103
9104 /* push global reference */
9105 sym = get_sym_ref(type, sec, addr, size);
9106 cval.ul = 0;
9107 vsetc(type, VT_CONST | VT_SYM, &cval);
9108 vtop->sym = sym;
9109 }
9110
9111 /* handles bounds now because the symbol must be defined
9112 before for the relocation */
9113 if (do_bounds_check) {
9114 unsigned long *bounds_ptr;
9115
9116 greloc(bounds_section, sym, bounds_section->data_offset, R_DATA_32);
9117 /* then add global bound info */
9118 bounds_ptr = section_ptr_add(bounds_section, 2 * sizeof(long));
9119 bounds_ptr[0] = 0; /* relocated */
9120 bounds_ptr[1] = size;
9121 }
9122 }
9123 if (has_init) {
9124 decl_initializer(type, sec, addr, 1, 0);
9125 /* restore parse state if needed */
9126 if (init_str.str) {
9127 tok_str_free(init_str.str);
9128 restore_parse_state(&saved_parse_state);
9129 }
9130 }
9131 no_alloc: ;
9132 }
9133
put_func_debug(Sym * sym)9134 void put_func_debug(Sym *sym)
9135 {
9136 char buf[512];
9137
9138 /* stabs info */
9139 /* XXX: we put here a dummy type */
9140 snprintf(buf, sizeof(buf), "%s:%c1",
9141 funcname, sym->type.t & VT_STATIC ? 'f' : 'F');
9142 put_stabs_r(buf, N_FUN, 0, file->line_num, 0,
9143 cur_text_section, sym->c);
9144 last_ind = 0;
9145 last_line_num = 0;
9146 }
9147
9148 /* parse an old style function declaration list */
9149 /* XXX: check multiple parameter */
func_decl_list(Sym * func_sym)9150 static void func_decl_list(Sym *func_sym)
9151 {
9152 AttributeDef ad;
9153 int v;
9154 Sym *s;
9155 CType btype, type;
9156
9157 /* parse each declaration */
9158 while (tok != '{' && tok != ';' && tok != ',' && tok != TOK_EOF) {
9159 if (!parse_btype(&btype, &ad))
9160 expect("declaration list");
9161 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9162 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9163 tok == ';') {
9164 /* we accept no variable after */
9165 } else {
9166 for(;;) {
9167 type = btype;
9168 type_decl(&type, &ad, &v, TYPE_DIRECT);
9169 /* find parameter in function parameter list */
9170 s = func_sym->next;
9171 while (s != NULL) {
9172 if ((s->v & ~SYM_FIELD) == v)
9173 goto found;
9174 s = s->next;
9175 }
9176 error("declaration for parameter '%s' but no such parameter",
9177 get_tok_str(v, NULL));
9178 found:
9179 /* check that no storage specifier except 'register' was given */
9180 if (type.t & VT_STORAGE)
9181 error("storage class specified for '%s'", get_tok_str(v, NULL));
9182 convert_parameter_type(&type);
9183 /* we can add the type (NOTE: it could be local to the function) */
9184 s->type = type;
9185 /* accept other parameters */
9186 if (tok == ',')
9187 next();
9188 else
9189 break;
9190 }
9191 }
9192 skip(';');
9193 }
9194 }
9195
9196 /* parse a function defined by symbol 'sym' and generate its code in
9197 'cur_text_section' */
gen_function(Sym * sym)9198 static void gen_function(Sym *sym)
9199 {
9200 int saved_nocode_wanted = nocode_wanted;
9201 nocode_wanted = 0;
9202 ind = cur_text_section->data_offset;
9203 /* NOTE: we patch the symbol size later */
9204 put_extern_sym(sym, cur_text_section, ind, 0);
9205 funcname = get_tok_str(sym->v, NULL);
9206 func_ind = ind;
9207 /* put debug symbol */
9208 if (do_debug)
9209 put_func_debug(sym);
9210 /* push a dummy symbol to enable local sym storage */
9211 sym_push2(&local_stack, SYM_FIELD, 0, 0);
9212 gfunc_prolog(&sym->type);
9213 rsym = 0;
9214 block(NULL, NULL, NULL, NULL, 0, 0);
9215 gsym(rsym);
9216 gfunc_epilog();
9217 cur_text_section->data_offset = ind;
9218 label_pop(&global_label_stack, NULL);
9219 sym_pop(&local_stack, NULL); /* reset local stack */
9220 /* end of function */
9221 /* patch symbol size */
9222 ((Elf32_Sym *)symtab_section->data)[sym->c].st_size =
9223 ind - func_ind;
9224 if (do_debug) {
9225 put_stabn(N_FUN, 0, 0, ind - func_ind);
9226 }
9227 funcname = ""; /* for safety */
9228 func_vt.t = VT_VOID; /* for safety */
9229 ind = 0; /* for safety */
9230 nocode_wanted = saved_nocode_wanted;
9231 }
9232
gen_inline_functions(void)9233 static void gen_inline_functions(void)
9234 {
9235 Sym *sym;
9236 CType *type;
9237 int *str, inline_generated;
9238
9239 /* iterate while inline function are referenced */
9240 for(;;) {
9241 inline_generated = 0;
9242 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9243 type = &sym->type;
9244 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9245 (type->t & (VT_STATIC | VT_INLINE)) ==
9246 (VT_STATIC | VT_INLINE) &&
9247 sym->c != 0) {
9248 /* the function was used: generate its code and
9249 convert it to a normal function */
9250 str = INLINE_DEF(sym->r);
9251 sym->r = VT_SYM | VT_CONST;
9252 sym->type.t &= ~VT_INLINE;
9253
9254 macro_ptr = str;
9255 next();
9256 cur_text_section = text_section;
9257 gen_function(sym);
9258 macro_ptr = NULL; /* fail safe */
9259
9260 tok_str_free(str);
9261 inline_generated = 1;
9262 }
9263 }
9264 if (!inline_generated)
9265 break;
9266 }
9267
9268 /* free all remaining inline function tokens */
9269 for(sym = global_stack; sym != NULL; sym = sym->prev) {
9270 type = &sym->type;
9271 if (((type->t & VT_BTYPE) == VT_FUNC) &&
9272 (type->t & (VT_STATIC | VT_INLINE)) ==
9273 (VT_STATIC | VT_INLINE)) {
9274 //gr printf("sym %d %s\n", sym->r, get_tok_str(sym->v, NULL));
9275 if (sym->r == (VT_SYM | VT_CONST)) //gr beware!
9276 continue;
9277 str = INLINE_DEF(sym->r);
9278 tok_str_free(str);
9279 sym->r = 0; /* fail safe */
9280 }
9281 }
9282 }
9283
9284 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
decl(int l)9285 static void decl(int l)
9286 {
9287 int v, has_init, r;
9288 CType type, btype;
9289 Sym *sym;
9290 AttributeDef ad;
9291
9292 while (1) {
9293 if (!parse_btype(&btype, &ad)) {
9294 /* skip redundant ';' */
9295 /* XXX: find more elegant solution */
9296 if (tok == ';') {
9297 next();
9298 continue;
9299 }
9300 if (l == VT_CONST &&
9301 (tok == TOK_ASM1 || tok == TOK_ASM2 || tok == TOK_ASM3)) {
9302 /* global asm block */
9303 asm_global_instr();
9304 continue;
9305 }
9306 /* special test for old K&R protos without explicit int
9307 type. Only accepted when defining global data */
9308 if (l == VT_LOCAL || tok < TOK_DEFINE)
9309 break;
9310 btype.t = VT_INT;
9311 }
9312 if (((btype.t & VT_BTYPE) == VT_ENUM ||
9313 (btype.t & VT_BTYPE) == VT_STRUCT) &&
9314 tok == ';') {
9315 /* we accept no variable after */
9316 next();
9317 continue;
9318 }
9319 while (1) { /* iterate thru each declaration */
9320 type = btype;
9321 type_decl(&type, &ad, &v, TYPE_DIRECT);
9322 #if 0
9323 {
9324 char buf[500];
9325 type_to_str(buf, sizeof(buf), t, get_tok_str(v, NULL));
9326 printf("type = '%s'\n", buf);
9327 }
9328 #endif
9329 if ((type.t & VT_BTYPE) == VT_FUNC) {
9330 /* if old style function prototype, we accept a
9331 declaration list */
9332 sym = type.ref;
9333 if (sym->c == FUNC_OLD)
9334 func_decl_list(sym);
9335 }
9336
9337 if (tok == '{') {
9338 if (l == VT_LOCAL)
9339 error("cannot use local functions");
9340 if ((type.t & VT_BTYPE) != VT_FUNC)
9341 expect("function definition");
9342
9343 /* reject abstract declarators in function definition */
9344 sym = type.ref;
9345 while ((sym = sym->next) != NULL)
9346 if (!(sym->v & ~SYM_FIELD))
9347 expect("identifier");
9348
9349 /* XXX: cannot do better now: convert extern line to static inline */
9350 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | VT_INLINE))
9351 type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
9352
9353 sym = sym_find(v);
9354 if (sym) {
9355 if ((sym->type.t & VT_BTYPE) != VT_FUNC)
9356 goto func_error1;
9357 /* specific case: if not func_call defined, we put
9358 the one of the prototype */
9359 /* XXX: should have default value */
9360 r = sym->type.ref->r;
9361 if (FUNC_CALL(r) != FUNC_CDECL
9362 && FUNC_CALL(type.ref->r) == FUNC_CDECL)
9363 FUNC_CALL(type.ref->r) = FUNC_CALL(r);
9364 if (FUNC_EXPORT(r))
9365 FUNC_EXPORT(type.ref->r) = 1;
9366
9367 if (!is_compatible_types(&sym->type, &type)) {
9368 func_error1:
9369 error("incompatible types for redefinition of '%s'",
9370 get_tok_str(v, NULL));
9371 }
9372 /* if symbol is already defined, then put complete type */
9373 sym->type = type;
9374 } else {
9375 /* put function symbol */
9376 sym = global_identifier_push(v, type.t, 0);
9377 sym->type.ref = type.ref;
9378 }
9379
9380 /* static inline functions are just recorded as a kind
9381 of macro. Their code will be emitted at the end of
9382 the compilation unit only if they are used */
9383 if ((type.t & (VT_INLINE | VT_STATIC)) ==
9384 (VT_INLINE | VT_STATIC)) {
9385 TokenString func_str;
9386 int block_level;
9387
9388 tok_str_new(&func_str);
9389
9390 block_level = 0;
9391 for(;;) {
9392 int t;
9393 if (tok == TOK_EOF)
9394 error("unexpected end of file");
9395 tok_str_add_tok(&func_str);
9396 t = tok;
9397 next();
9398 if (t == '{') {
9399 block_level++;
9400 } else if (t == '}') {
9401 block_level--;
9402 if (block_level == 0)
9403 break;
9404 }
9405 }
9406 tok_str_add(&func_str, -1);
9407 tok_str_add(&func_str, 0);
9408 INLINE_DEF(sym->r) = func_str.str;
9409 } else {
9410 /* compute text section */
9411 cur_text_section = ad.section;
9412 if (!cur_text_section)
9413 cur_text_section = text_section;
9414 sym->r = VT_SYM | VT_CONST;
9415 gen_function(sym);
9416 }
9417 break;
9418 } else {
9419 if (btype.t & VT_TYPEDEF) {
9420 /* save typedefed type */
9421 /* XXX: test storage specifiers ? */
9422 sym = sym_push(v, &type, 0, 0);
9423 sym->type.t |= VT_TYPEDEF;
9424 } else if ((type.t & VT_BTYPE) == VT_FUNC) {
9425 /* external function definition */
9426 /* specific case for func_call attribute */
9427 if (ad.func_attr)
9428 type.ref->r = ad.func_attr;
9429 external_sym(v, &type, 0);
9430 } else {
9431 /* not lvalue if array */
9432 r = 0;
9433 if (!(type.t & VT_ARRAY))
9434 r |= lvalue_type(type.t);
9435 has_init = (tok == '=');
9436 if ((btype.t & VT_EXTERN) ||
9437 ((type.t & VT_ARRAY) && (type.t & VT_STATIC) &&
9438 !has_init && l == VT_CONST && type.ref->c < 0)) {
9439 /* external variable */
9440 /* NOTE: as GCC, uninitialized global static
9441 arrays of null size are considered as
9442 extern */
9443 external_sym(v, &type, r);
9444 } else {
9445 type.t |= (btype.t & VT_STATIC); /* Retain "static". */
9446 if (type.t & VT_STATIC)
9447 r |= VT_CONST;
9448 else
9449 r |= l;
9450 if (has_init)
9451 next();
9452 decl_initializer_alloc(&type, &ad, r,
9453 has_init, v, l);
9454 }
9455 }
9456 if (tok != ',') {
9457 skip(';');
9458 break;
9459 }
9460 next();
9461 }
9462 }
9463 }
9464 }
9465
9466 /* better than nothing, but needs extension to handle '-E' option
9467 correctly too */
preprocess_init(TCCState * s1)9468 static void preprocess_init(TCCState *s1)
9469 {
9470 s1->include_stack_ptr = s1->include_stack;
9471 /* XXX: move that before to avoid having to initialize
9472 file->ifdef_stack_ptr ? */
9473 s1->ifdef_stack_ptr = s1->ifdef_stack;
9474 file->ifdef_stack_ptr = s1->ifdef_stack_ptr;
9475
9476 /* XXX: not ANSI compliant: bound checking says error */
9477 vtop = vstack - 1;
9478 s1->pack_stack[0] = 0;
9479 s1->pack_stack_ptr = s1->pack_stack;
9480 }
9481
9482 /* compile the C file opened in 'file'. Return non zero if errors. */
tcc_compile(TCCState * s1)9483 static int tcc_compile(TCCState *s1)
9484 {
9485 Sym *define_start;
9486 char buf[512];
9487 volatile int section_sym;
9488
9489 #ifdef INC_DEBUG
9490 printf("%s: **** new file\n", file->filename);
9491 #endif
9492 preprocess_init(s1);
9493
9494 funcname = "";
9495 anon_sym = SYM_FIRST_ANOM;
9496
9497 /* file info: full path + filename */
9498 section_sym = 0; /* avoid warning */
9499 if (do_debug) {
9500 section_sym = put_elf_sym(symtab_section, 0, 0,
9501 ELF32_ST_INFO(STB_LOCAL, STT_SECTION), 0,
9502 text_section->sh_num, NULL);
9503 getcwd(buf, sizeof(buf));
9504 #ifdef _WIN32
9505 normalize_slashes(buf);
9506 #endif
9507 pstrcat(buf, sizeof(buf), "/");
9508 put_stabs_r(buf, N_SO, 0, 0,
9509 text_section->data_offset, text_section, section_sym);
9510 put_stabs_r(file->filename, N_SO, 0, 0,
9511 text_section->data_offset, text_section, section_sym);
9512 }
9513 /* an elf symbol of type STT_FILE must be put so that STB_LOCAL
9514 symbols can be safely used */
9515 put_elf_sym(symtab_section, 0, 0,
9516 ELF32_ST_INFO(STB_LOCAL, STT_FILE), 0,
9517 SHN_ABS, file->filename);
9518
9519 /* define some often used types */
9520 int_type.t = VT_INT;
9521
9522 char_pointer_type.t = VT_BYTE;
9523 mk_pointer(&char_pointer_type);
9524
9525 func_old_type.t = VT_FUNC;
9526 func_old_type.ref = sym_push(SYM_FIELD, &int_type, FUNC_CDECL, FUNC_OLD);
9527
9528 #if defined(TCC_ARM_EABI) && defined(TCC_ARM_VFP)
9529 float_type.t = VT_FLOAT;
9530 double_type.t = VT_DOUBLE;
9531
9532 func_float_type.t = VT_FUNC;
9533 func_float_type.ref = sym_push(SYM_FIELD, &float_type, FUNC_CDECL, FUNC_OLD);
9534 func_double_type.t = VT_FUNC;
9535 func_double_type.ref = sym_push(SYM_FIELD, &double_type, FUNC_CDECL, FUNC_OLD);
9536 #endif
9537
9538 #if 0
9539 /* define 'void *alloca(unsigned int)' builtin function */
9540 {
9541 Sym *s1;
9542
9543 p = anon_sym++;
9544 sym = sym_push(p, mk_pointer(VT_VOID), FUNC_CDECL, FUNC_NEW);
9545 s1 = sym_push(SYM_FIELD, VT_UNSIGNED | VT_INT, 0, 0);
9546 s1->next = NULL;
9547 sym->next = s1;
9548 sym_push(TOK_alloca, VT_FUNC | (p << VT_STRUCT_SHIFT), VT_CONST, 0);
9549 }
9550 #endif
9551
9552 define_start = define_stack;
9553 nocode_wanted = 1;
9554
9555 if (setjmp(s1->error_jmp_buf) == 0) {
9556 s1->nb_errors = 0;
9557 s1->error_set_jmp_enabled = 1;
9558
9559 ch = file->buf_ptr[0];
9560 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9561 parse_flags = PARSE_FLAG_PREPROCESS | PARSE_FLAG_TOK_NUM;
9562 next();
9563 decl(VT_CONST);
9564 if (tok != TOK_EOF)
9565 expect("declaration");
9566
9567 /* end of translation unit info */
9568 if (do_debug) {
9569 put_stabs_r(NULL, N_SO, 0, 0,
9570 text_section->data_offset, text_section, section_sym);
9571 }
9572 }
9573 s1->error_set_jmp_enabled = 0;
9574
9575 /* reset define stack, but leave -Dsymbols (may be incorrect if
9576 they are undefined) */
9577 free_defines(define_start);
9578
9579 gen_inline_functions();
9580
9581 sym_pop(&global_stack, NULL);
9582
9583 return s1->nb_errors != 0 ? -1 : 0;
9584 }
9585
9586 /* Preprocess the current file */
9587 /* XXX: add line and file infos, add options to preserve spaces */
tcc_preprocess(TCCState * s1)9588 static int tcc_preprocess(TCCState *s1)
9589 {
9590 Sym *define_start;
9591 int last_is_space;
9592
9593 preprocess_init(s1);
9594
9595 define_start = define_stack;
9596
9597 ch = file->buf_ptr[0];
9598 tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
9599 parse_flags = PARSE_FLAG_ASM_COMMENTS | PARSE_FLAG_PREPROCESS |
9600 PARSE_FLAG_LINEFEED;
9601 last_is_space = 1;
9602 next();
9603 for(;;) {
9604 if (tok == TOK_EOF) {
9605 break;
9606 } else if (tok == TOK_LINEFEED) {
9607 last_is_space = 1;
9608 } else {
9609 if (!last_is_space)
9610 fputc(' ', s1->outfile);
9611 last_is_space = 0;
9612 }
9613 fputs(get_tok_str(tok, &tokc), s1->outfile);
9614 next();
9615 }
9616 free_defines(define_start);
9617 return 0;
9618 }
9619
9620 #ifdef LIBTCC
tcc_compile_string(TCCState * s,const char * str)9621 int tcc_compile_string(TCCState *s, const char *str)
9622 {
9623 BufferedFile bf1, *bf = &bf1;
9624 int ret, len;
9625 char *buf;
9626
9627 /* init file structure */
9628 bf->fd = -1;
9629 /* XXX: avoid copying */
9630 len = strlen(str);
9631 buf = tcc_malloc(len + 1);
9632 if (!buf)
9633 return -1;
9634 memcpy(buf, str, len);
9635 buf[len] = CH_EOB;
9636 bf->buf_ptr = buf;
9637 bf->buf_end = buf + len;
9638 pstrcpy(bf->filename, sizeof(bf->filename), "<string>");
9639 bf->line_num = 1;
9640 file = bf;
9641
9642 ret = tcc_compile(s);
9643
9644 tcc_free(buf);
9645
9646 /* currently, no need to close */
9647 return ret;
9648 }
9649 #endif
9650
9651 /* define a preprocessor symbol. A value can also be provided with the '=' operator */
tcc_define_symbol(TCCState * s1,const char * sym,const char * value)9652 void tcc_define_symbol(TCCState *s1, const char *sym, const char *value)
9653 {
9654 BufferedFile bf1, *bf = &bf1;
9655
9656 pstrcpy(bf->buffer, IO_BUF_SIZE, sym);
9657 pstrcat(bf->buffer, IO_BUF_SIZE, " ");
9658 /* default value */
9659 if (!value)
9660 value = "1";
9661 pstrcat(bf->buffer, IO_BUF_SIZE, value);
9662
9663 /* init file structure */
9664 bf->fd = -1;
9665 bf->buf_ptr = bf->buffer;
9666 bf->buf_end = bf->buffer + strlen(bf->buffer);
9667 *bf->buf_end = CH_EOB;
9668 bf->filename[0] = '\0';
9669 bf->line_num = 1;
9670 file = bf;
9671
9672 s1->include_stack_ptr = s1->include_stack;
9673
9674 /* parse with define parser */
9675 ch = file->buf_ptr[0];
9676 next_nomacro();
9677 parse_define();
9678 file = NULL;
9679 }
9680
9681 /* undefine a preprocessor symbol */
tcc_undefine_symbol(TCCState * s1,const char * sym)9682 void tcc_undefine_symbol(TCCState *s1, const char *sym)
9683 {
9684 TokenSym *ts;
9685 Sym *s;
9686 ts = tok_alloc(sym, strlen(sym));
9687 s = define_find(ts->tok);
9688 /* undefine symbol by putting an invalid name */
9689 if (s)
9690 define_undef(s);
9691 }
9692
9693 #ifdef CONFIG_TCC_ASM
9694
9695 #ifdef TCC_TARGET_I386
9696 #include "i386-asm.c"
9697 #endif
9698 #include "tccasm.c"
9699
9700 #else
asm_instr(void)9701 static void asm_instr(void)
9702 {
9703 error("inline asm() not supported");
9704 }
asm_global_instr(void)9705 static void asm_global_instr(void)
9706 {
9707 error("inline asm() not supported");
9708 }
9709 #endif
9710
9711 #include "tccelf.c"
9712
9713 #ifdef TCC_TARGET_COFF
9714 #include "tcccoff.c"
9715 #endif
9716
9717 #ifdef TCC_TARGET_PE
9718 #include "tccpe.c"
9719 #endif
9720
9721 /* print the position in the source file of PC value 'pc' by reading
9722 the stabs debug information */
rt_printline(unsigned long wanted_pc)9723 static void rt_printline(unsigned long wanted_pc)
9724 {
9725 Stab_Sym *sym, *sym_end;
9726 char func_name[128], last_func_name[128];
9727 unsigned long func_addr, last_pc, pc;
9728 const char *incl_files[INCLUDE_STACK_SIZE];
9729 int incl_index, len, last_line_num, i;
9730 const char *str, *p;
9731
9732 fprintf(stderr, "0x%08lx:", wanted_pc);
9733
9734 func_name[0] = '\0';
9735 func_addr = 0;
9736 incl_index = 0;
9737 last_func_name[0] = '\0';
9738 last_pc = 0xffffffff;
9739 last_line_num = 1;
9740 sym = (Stab_Sym *)stab_section->data + 1;
9741 sym_end = (Stab_Sym *)(stab_section->data + stab_section->data_offset);
9742 while (sym < sym_end) {
9743 switch(sym->n_type) {
9744 /* function start or end */
9745 case N_FUN:
9746 if (sym->n_strx == 0) {
9747 /* we test if between last line and end of function */
9748 pc = sym->n_value + func_addr;
9749 if (wanted_pc >= last_pc && wanted_pc < pc)
9750 goto found;
9751 func_name[0] = '\0';
9752 func_addr = 0;
9753 } else {
9754 str = stabstr_section->data + sym->n_strx;
9755 p = strchr(str, ':');
9756 if (!p) {
9757 pstrcpy(func_name, sizeof(func_name), str);
9758 } else {
9759 len = p - str;
9760 if (len > sizeof(func_name) - 1)
9761 len = sizeof(func_name) - 1;
9762 memcpy(func_name, str, len);
9763 func_name[len] = '\0';
9764 }
9765 func_addr = sym->n_value;
9766 }
9767 break;
9768 /* line number info */
9769 case N_SLINE:
9770 pc = sym->n_value + func_addr;
9771 if (wanted_pc >= last_pc && wanted_pc < pc)
9772 goto found;
9773 last_pc = pc;
9774 last_line_num = sym->n_desc;
9775 /* XXX: slow! */
9776 strcpy(last_func_name, func_name);
9777 break;
9778 /* include files */
9779 case N_BINCL:
9780 str = stabstr_section->data + sym->n_strx;
9781 add_incl:
9782 if (incl_index < INCLUDE_STACK_SIZE) {
9783 incl_files[incl_index++] = str;
9784 }
9785 break;
9786 case N_EINCL:
9787 if (incl_index > 1)
9788 incl_index--;
9789 break;
9790 case N_SO:
9791 if (sym->n_strx == 0) {
9792 incl_index = 0; /* end of translation unit */
9793 } else {
9794 str = stabstr_section->data + sym->n_strx;
9795 /* do not add path */
9796 len = strlen(str);
9797 if (len > 0 && str[len - 1] != '/')
9798 goto add_incl;
9799 }
9800 break;
9801 }
9802 sym++;
9803 }
9804
9805 /* second pass: we try symtab symbols (no line number info) */
9806 incl_index = 0;
9807 {
9808 Elf32_Sym *sym, *sym_end;
9809 int type;
9810
9811 sym_end = (Elf32_Sym *)(symtab_section->data + symtab_section->data_offset);
9812 for(sym = (Elf32_Sym *)symtab_section->data + 1;
9813 sym < sym_end;
9814 sym++) {
9815 type = ELF32_ST_TYPE(sym->st_info);
9816 if (type == STT_FUNC) {
9817 if (wanted_pc >= sym->st_value &&
9818 wanted_pc < sym->st_value + sym->st_size) {
9819 pstrcpy(last_func_name, sizeof(last_func_name),
9820 strtab_section->data + sym->st_name);
9821 goto found;
9822 }
9823 }
9824 }
9825 }
9826 /* did not find any info: */
9827 fprintf(stderr, " ???\n");
9828 return;
9829 found:
9830 if (last_func_name[0] != '\0') {
9831 fprintf(stderr, " %s()", last_func_name);
9832 }
9833 if (incl_index > 0) {
9834 fprintf(stderr, " (%s:%d",
9835 incl_files[incl_index - 1], last_line_num);
9836 for(i = incl_index - 2; i >= 0; i--)
9837 fprintf(stderr, ", included from %s", incl_files[i]);
9838 fprintf(stderr, ")");
9839 }
9840 fprintf(stderr, "\n");
9841 }
9842
9843 #if !defined(_WIN32) && !defined(CONFIG_TCCBOOT)
9844
9845 #ifdef __i386__
9846
9847 /* fix for glibc 2.1 */
9848 #ifndef REG_EIP
9849 #define REG_EIP EIP
9850 #define REG_EBP EBP
9851 #endif
9852
9853 /* return the PC at frame level 'level'. Return non zero if not found */
rt_get_caller_pc(unsigned long * paddr,ucontext_t * uc,int level)9854 static int rt_get_caller_pc(unsigned long *paddr,
9855 ucontext_t *uc, int level)
9856 {
9857 unsigned long fp;
9858 int i;
9859
9860 if (level == 0) {
9861 #if defined(__FreeBSD__)
9862 *paddr = uc->uc_mcontext.mc_eip;
9863 #elif defined(__dietlibc__)
9864 *paddr = uc->uc_mcontext.eip;
9865 #else
9866 *paddr = uc->uc_mcontext.gregs[REG_EIP];
9867 #endif
9868 return 0;
9869 } else {
9870 #if defined(__FreeBSD__)
9871 fp = uc->uc_mcontext.mc_ebp;
9872 #elif defined(__dietlibc__)
9873 fp = uc->uc_mcontext.ebp;
9874 #else
9875 fp = uc->uc_mcontext.gregs[REG_EBP];
9876 #endif
9877 for(i=1;i<level;i++) {
9878 /* XXX: check address validity with program info */
9879 if (fp <= 0x1000 || fp >= 0xc0000000)
9880 return -1;
9881 fp = ((unsigned long *)fp)[0];
9882 }
9883 *paddr = ((unsigned long *)fp)[1];
9884 return 0;
9885 }
9886 }
9887 #else
9888
9889 #warning add arch specific rt_get_caller_pc()
9890
rt_get_caller_pc(unsigned long * paddr,ucontext_t * uc,int level)9891 static int rt_get_caller_pc(unsigned long *paddr,
9892 ucontext_t *uc, int level)
9893 {
9894 return -1;
9895 }
9896 #endif
9897
9898 /* emit a run time error at position 'pc' */
rt_error(ucontext_t * uc,const char * fmt,...)9899 void rt_error(ucontext_t *uc, const char *fmt, ...)
9900 {
9901 va_list ap;
9902 unsigned long pc;
9903 int i;
9904
9905 va_start(ap, fmt);
9906 fprintf(stderr, "Runtime error: ");
9907 vfprintf(stderr, fmt, ap);
9908 fprintf(stderr, "\n");
9909 for(i=0;i<num_callers;i++) {
9910 if (rt_get_caller_pc(&pc, uc, i) < 0)
9911 break;
9912 if (i == 0)
9913 fprintf(stderr, "at ");
9914 else
9915 fprintf(stderr, "by ");
9916 rt_printline(pc);
9917 }
9918 exit(255);
9919 va_end(ap);
9920 }
9921
9922 /* signal handler for fatal errors */
sig_error(int signum,siginfo_t * siginf,void * puc)9923 static void sig_error(int signum, siginfo_t *siginf, void *puc)
9924 {
9925 ucontext_t *uc = puc;
9926
9927 switch(signum) {
9928 case SIGFPE:
9929 switch(siginf->si_code) {
9930 case FPE_INTDIV:
9931 case FPE_FLTDIV:
9932 rt_error(uc, "division by zero");
9933 break;
9934 default:
9935 rt_error(uc, "floating point exception");
9936 break;
9937 }
9938 break;
9939 case SIGBUS:
9940 case SIGSEGV:
9941 if (rt_bound_error_msg && *rt_bound_error_msg)
9942 rt_error(uc, *rt_bound_error_msg);
9943 else
9944 rt_error(uc, "dereferencing invalid pointer");
9945 break;
9946 case SIGILL:
9947 rt_error(uc, "illegal instruction");
9948 break;
9949 case SIGABRT:
9950 rt_error(uc, "abort() called");
9951 break;
9952 default:
9953 rt_error(uc, "caught signal %d", signum);
9954 break;
9955 }
9956 exit(255);
9957 }
9958 #endif
9959
9960 /* do all relocations (needed before using tcc_get_symbol()) */
tcc_relocate(TCCState * s1)9961 int tcc_relocate(TCCState *s1)
9962 {
9963 Section *s;
9964 int i;
9965
9966 s1->nb_errors = 0;
9967
9968 #ifdef TCC_TARGET_PE
9969 pe_add_runtime(s1);
9970 #else
9971 tcc_add_runtime(s1);
9972 #endif
9973
9974 relocate_common_syms();
9975
9976 tcc_add_linker_symbols(s1);
9977 #ifndef TCC_TARGET_PE
9978 build_got_entries(s1);
9979 #endif
9980 /* compute relocation address : section are relocated in place. We
9981 also alloc the bss space */
9982 for(i = 1; i < s1->nb_sections; i++) {
9983 s = s1->sections[i];
9984 if (s->sh_flags & SHF_ALLOC) {
9985 if (s->sh_type == SHT_NOBITS)
9986 s->data = tcc_mallocz(s->data_offset);
9987 s->sh_addr = (unsigned long)s->data;
9988 }
9989 }
9990
9991 relocate_syms(s1, 1);
9992
9993 if (s1->nb_errors != 0)
9994 return -1;
9995
9996 /* relocate each section */
9997 for(i = 1; i < s1->nb_sections; i++) {
9998 s = s1->sections[i];
9999 if (s->reloc)
10000 relocate_section(s1, s);
10001 }
10002
10003 /* mark executable sections as executable in memory */
10004 for(i = 1; i < s1->nb_sections; i++) {
10005 s = s1->sections[i];
10006 if ((s->sh_flags & (SHF_ALLOC | SHF_EXECINSTR)) ==
10007 (SHF_ALLOC | SHF_EXECINSTR))
10008 set_pages_executable(s->data, s->data_offset);
10009 }
10010 return 0;
10011 }
10012
10013 /* launch the compiled program with the given arguments */
tcc_run(TCCState * s1,int argc,char ** argv)10014 int tcc_run(TCCState *s1, int argc, char **argv)
10015 {
10016 int (*prog_main)(int, char **);
10017
10018 if (tcc_relocate(s1) < 0)
10019 return -1;
10020
10021 prog_main = tcc_get_symbol_err(s1, "main");
10022
10023 if (do_debug) {
10024 #if defined(_WIN32) || defined(CONFIG_TCCBOOT)
10025 error("debug mode currently not available for Windows");
10026 #else
10027 struct sigaction sigact;
10028 /* install TCC signal handlers to print debug info on fatal
10029 runtime errors */
10030 sigact.sa_flags = SA_SIGINFO | SA_RESETHAND;
10031 sigact.sa_sigaction = sig_error;
10032 sigemptyset(&sigact.sa_mask);
10033 sigaction(SIGFPE, &sigact, NULL);
10034 sigaction(SIGILL, &sigact, NULL);
10035 sigaction(SIGSEGV, &sigact, NULL);
10036 sigaction(SIGBUS, &sigact, NULL);
10037 sigaction(SIGABRT, &sigact, NULL);
10038 #endif
10039 }
10040
10041 #ifdef CONFIG_TCC_BCHECK
10042 if (do_bounds_check) {
10043 void (*bound_init)(void);
10044
10045 /* set error function */
10046 rt_bound_error_msg = (void *)tcc_get_symbol_err(s1,
10047 "__bound_error_msg");
10048
10049 /* XXX: use .init section so that it also work in binary ? */
10050 bound_init = (void *)tcc_get_symbol_err(s1, "__bound_init");
10051 bound_init();
10052 }
10053 #endif
10054 return (*prog_main)(argc, argv);
10055 }
10056
tcc_new(void)10057 TCCState *tcc_new(void)
10058 {
10059 const char *p, *r;
10060 TCCState *s;
10061 TokenSym *ts;
10062 int i, c;
10063
10064 s = tcc_mallocz(sizeof(TCCState));
10065 if (!s)
10066 return NULL;
10067 tcc_state = s;
10068 s->output_type = TCC_OUTPUT_MEMORY;
10069
10070 /* init isid table */
10071 for(i=0;i<256;i++)
10072 isidnum_table[i] = isid(i) || isnum(i);
10073
10074 /* add all tokens */
10075 table_ident = NULL;
10076 memset(hash_ident, 0, TOK_HASH_SIZE * sizeof(TokenSym *));
10077
10078 tok_ident = TOK_IDENT;
10079 p = tcc_keywords;
10080 while (*p) {
10081 r = p;
10082 for(;;) {
10083 c = *r++;
10084 if (c == '\0')
10085 break;
10086 }
10087 ts = tok_alloc(p, r - p - 1);
10088 p = r;
10089 }
10090
10091 /* we add dummy defines for some special macros to speed up tests
10092 and to have working defined() */
10093 define_push(TOK___LINE__, MACRO_OBJ, NULL, NULL);
10094 define_push(TOK___FILE__, MACRO_OBJ, NULL, NULL);
10095 define_push(TOK___DATE__, MACRO_OBJ, NULL, NULL);
10096 define_push(TOK___TIME__, MACRO_OBJ, NULL, NULL);
10097
10098 /* standard defines */
10099 tcc_define_symbol(s, "__STDC__", NULL);
10100 tcc_define_symbol(s, "__STDC_VERSION__", "199901L");
10101 #if defined(TCC_TARGET_I386)
10102 tcc_define_symbol(s, "__i386__", NULL);
10103 #endif
10104 #if defined(TCC_TARGET_ARM)
10105 tcc_define_symbol(s, "__ARM_ARCH_4__", NULL);
10106 tcc_define_symbol(s, "__arm_elf__", NULL);
10107 tcc_define_symbol(s, "__arm_elf", NULL);
10108 tcc_define_symbol(s, "arm_elf", NULL);
10109 tcc_define_symbol(s, "__arm__", NULL);
10110 tcc_define_symbol(s, "__arm", NULL);
10111 tcc_define_symbol(s, "arm", NULL);
10112 tcc_define_symbol(s, "__APCS_32__", NULL);
10113 #endif
10114 #ifdef TCC_TARGET_PE
10115 tcc_define_symbol(s, "_WIN32", NULL);
10116 #else
10117 tcc_define_symbol(s, "__unix__", NULL);
10118 tcc_define_symbol(s, "__unix", NULL);
10119 #if defined(__linux)
10120 tcc_define_symbol(s, "__linux__", NULL);
10121 tcc_define_symbol(s, "__linux", NULL);
10122 #endif
10123 #endif
10124 /* tiny C specific defines */
10125 tcc_define_symbol(s, "__TINYC__", NULL);
10126
10127 /* tiny C & gcc defines */
10128 tcc_define_symbol(s, "__SIZE_TYPE__", "unsigned int");
10129 tcc_define_symbol(s, "__PTRDIFF_TYPE__", "int");
10130 #ifdef TCC_TARGET_PE
10131 tcc_define_symbol(s, "__WCHAR_TYPE__", "unsigned short");
10132 #else
10133 tcc_define_symbol(s, "__WCHAR_TYPE__", "int");
10134 #endif
10135
10136 #ifndef TCC_TARGET_PE
10137 /* default library paths */
10138 tcc_add_library_path(s, "/usr/local/lib");
10139 tcc_add_library_path(s, "/usr/lib");
10140 tcc_add_library_path(s, "/lib");
10141 #endif
10142
10143 /* no section zero */
10144 dynarray_add((void ***)&s->sections, &s->nb_sections, NULL);
10145
10146 /* create standard sections */
10147 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
10148 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
10149 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
10150
10151 /* symbols are always generated for linking stage */
10152 symtab_section = new_symtab(s, ".symtab", SHT_SYMTAB, 0,
10153 ".strtab",
10154 ".hashtab", SHF_PRIVATE);
10155 strtab_section = symtab_section->link;
10156
10157 /* private symbol table for dynamic symbols */
10158 s->dynsymtab_section = new_symtab(s, ".dynsymtab", SHT_SYMTAB, SHF_PRIVATE,
10159 ".dynstrtab",
10160 ".dynhashtab", SHF_PRIVATE);
10161 s->alacarte_link = 1;
10162
10163 #ifdef CHAR_IS_UNSIGNED
10164 s->char_is_unsigned = 1;
10165 #endif
10166 #if defined(TCC_TARGET_PE) && 0
10167 /* XXX: currently the PE linker is not ready to support that */
10168 s->leading_underscore = 1;
10169 #endif
10170 strcpy(tcc_lib_path, CONFIG_TCCDIR);
10171 return s;
10172 }
10173
SetLibPath(const char * path)10174 void SetLibPath(const char *path) {
10175 strcpy(tcc_lib_path, path);
10176 }
10177
NoStdlib(TCCState * s)10178 void NoStdlib(TCCState *s) {
10179 s->nostdlib = 1;
10180 }
10181
tcc_delete(TCCState * s1)10182 void tcc_delete(TCCState *s1)
10183 {
10184 int i, n;
10185
10186 /* free -D defines */
10187 free_defines(NULL);
10188
10189 /* free tokens */
10190 n = tok_ident - TOK_IDENT;
10191 for(i = 0; i < n; i++)
10192 tcc_free(table_ident[i]);
10193 tcc_free(table_ident);
10194
10195 /* free all sections */
10196
10197 free_section(symtab_section->hash);
10198
10199 free_section(s1->dynsymtab_section->hash);
10200 free_section(s1->dynsymtab_section->link);
10201 free_section(s1->dynsymtab_section);
10202
10203 for(i = 1; i < s1->nb_sections; i++)
10204 free_section(s1->sections[i]);
10205 tcc_free(s1->sections);
10206
10207 /* free loaded dlls array */
10208 dynarray_reset(&s1->loaded_dlls, &s1->nb_loaded_dlls);
10209
10210 /* free library paths */
10211 dynarray_reset(&s1->library_paths, &s1->nb_library_paths);
10212
10213 /* free include paths */
10214 dynarray_reset(&s1->cached_includes, &s1->nb_cached_includes);
10215 dynarray_reset(&s1->include_paths, &s1->nb_include_paths);
10216 dynarray_reset(&s1->sysinclude_paths, &s1->nb_sysinclude_paths);
10217
10218 tcc_free(s1);
10219 }
10220
tcc_add_include_path(TCCState * s1,const char * pathname)10221 int tcc_add_include_path(TCCState *s1, const char *pathname)
10222 {
10223 char *pathname1;
10224
10225 pathname1 = tcc_strdup(pathname);
10226 dynarray_add((void ***)&s1->include_paths, &s1->nb_include_paths, pathname1);
10227 return 0;
10228 }
10229
tcc_add_sysinclude_path(TCCState * s1,const char * pathname)10230 int tcc_add_sysinclude_path(TCCState *s1, const char *pathname)
10231 {
10232 char *pathname1;
10233
10234 pathname1 = tcc_strdup(pathname);
10235 dynarray_add((void ***)&s1->sysinclude_paths, &s1->nb_sysinclude_paths, pathname1);
10236 return 0;
10237 }
10238
tcc_add_file_internal(TCCState * s1,const char * filename,int flags)10239 static int tcc_add_file_internal(TCCState *s1, const char *filename, int flags)
10240 {
10241 const char *ext;
10242 Elf32_Ehdr ehdr;
10243 int fd, ret;
10244 BufferedFile *saved_file;
10245
10246 /* find source file type with extension */
10247 ext = tcc_fileextension(filename);
10248 if (ext[0])
10249 ext++;
10250
10251 /* open the file */
10252 saved_file = file;
10253 file = tcc_open(s1, filename);
10254 if (!file) {
10255 if (flags & AFF_PRINT_ERROR) {
10256 error_noabort("file '%s' not found", filename);
10257 }
10258 ret = -1;
10259 goto fail1;
10260 }
10261
10262 if (flags & AFF_PREPROCESS) {
10263 ret = tcc_preprocess(s1);
10264 } else if (!ext[0] || !strcmp(ext, "c")) {
10265 /* C file assumed */
10266 ret = tcc_compile(s1);
10267 } else
10268 #ifdef CONFIG_TCC_ASM
10269 if (!strcmp(ext, "S")) {
10270 /* preprocessed assembler */
10271 ret = tcc_assemble(s1, 1);
10272 } else if (!strcmp(ext, "s")) {
10273 /* non preprocessed assembler */
10274 ret = tcc_assemble(s1, 0);
10275 } else
10276 #endif
10277 #ifdef TCC_TARGET_PE
10278 if (!strcmp(ext, "def")) {
10279 ret = pe_load_def_file(s1, file->fd);
10280 } else
10281 #endif
10282 {
10283 fd = file->fd;
10284 /* assume executable format: auto guess file type */
10285 ret = read(fd, &ehdr, sizeof(ehdr));
10286 lseek(fd, 0, SEEK_SET);
10287 if (ret <= 0) {
10288 error_noabort("could not read header");
10289 goto fail;
10290 } else if (ret != sizeof(ehdr)) {
10291 goto try_load_script;
10292 }
10293
10294 if (ehdr.e_ident[0] == ELFMAG0 &&
10295 ehdr.e_ident[1] == ELFMAG1 &&
10296 ehdr.e_ident[2] == ELFMAG2 &&
10297 ehdr.e_ident[3] == ELFMAG3) {
10298 file->line_num = 0; /* do not display line number if error */
10299 if (ehdr.e_type == ET_REL) {
10300 ret = tcc_load_object_file(s1, fd, 0);
10301 } else if (ehdr.e_type == ET_DYN) {
10302 if (s1->output_type == TCC_OUTPUT_MEMORY) {
10303 #ifdef TCC_TARGET_PE
10304 ret = -1;
10305 #else
10306 void *h;
10307 h = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
10308 if (h)
10309 ret = 0;
10310 else
10311 ret = -1;
10312 #endif
10313 } else {
10314 ret = tcc_load_dll(s1, fd, filename,
10315 (flags & AFF_REFERENCED_DLL) != 0);
10316 }
10317 } else {
10318 error_noabort("unrecognized ELF file");
10319 goto fail;
10320 }
10321 } else if (memcmp((char *)&ehdr, ARMAG, 8) == 0) {
10322 file->line_num = 0; /* do not display line number if error */
10323 ret = tcc_load_archive(s1, fd);
10324 } else
10325 #ifdef TCC_TARGET_COFF
10326 if (*(uint16_t *)(&ehdr) == COFF_C67_MAGIC) {
10327 ret = tcc_load_coff(s1, fd);
10328 } else
10329 #endif
10330 #ifdef TCC_TARGET_PE
10331 if (pe_test_res_file(&ehdr, ret)) {
10332 ret = pe_load_res_file(s1, fd);
10333 } else
10334 #endif
10335 {
10336 /* as GNU ld, consider it is an ld script if not recognized */
10337 try_load_script:
10338 ret = tcc_load_ldscript(s1);
10339 if (ret < 0) {
10340 error_noabort("unrecognized file type");
10341 goto fail;
10342 }
10343 }
10344 }
10345 the_end:
10346 tcc_close(file);
10347 fail1:
10348 file = saved_file;
10349 return ret;
10350 fail:
10351 ret = -1;
10352 goto the_end;
10353 }
10354
tcc_add_file(TCCState * s,const char * filename)10355 int tcc_add_file(TCCState *s, const char *filename)
10356 {
10357 return tcc_add_file_internal(s, filename, AFF_PRINT_ERROR);
10358 }
10359
tcc_add_library_path(TCCState * s,const char * pathname)10360 int tcc_add_library_path(TCCState *s, const char *pathname)
10361 {
10362 char *pathname1;
10363
10364 pathname1 = tcc_strdup(pathname);
10365 dynarray_add((void ***)&s->library_paths, &s->nb_library_paths, pathname1);
10366 return 0;
10367 }
10368
10369 /* find and load a dll. Return non zero if not found */
10370 /* XXX: add '-rpath' option support ? */
tcc_add_dll(TCCState * s,const char * filename,int flags)10371 static int tcc_add_dll(TCCState *s, const char *filename, int flags)
10372 {
10373 char buf[1024];
10374 int i;
10375
10376 for(i = 0; i < s->nb_library_paths; i++) {
10377 snprintf(buf, sizeof(buf), "%s/%s",
10378 s->library_paths[i], filename);
10379 if (tcc_add_file_internal(s, buf, flags) == 0)
10380 return 0;
10381 }
10382 return -1;
10383 }
10384
10385 /* the library name is the same as the argument of the '-l' option */
tcc_add_library(TCCState * s,const char * libraryname)10386 int tcc_add_library(TCCState *s, const char *libraryname)
10387 {
10388 char buf[1024];
10389 int i;
10390
10391 /* first we look for the dynamic library if not static linking */
10392 if (!s->static_link) {
10393 #ifdef TCC_TARGET_PE
10394 snprintf(buf, sizeof(buf), "%s.def", libraryname);
10395 #else
10396 snprintf(buf, sizeof(buf), "lib%s.so", libraryname);
10397 #endif
10398 if (tcc_add_dll(s, buf, 0) == 0)
10399 return 0;
10400 }
10401
10402 /* then we look for the static library */
10403 for(i = 0; i < s->nb_library_paths; i++) {
10404 snprintf(buf, sizeof(buf), "%s/lib%s.a",
10405 s->library_paths[i], libraryname);
10406 if (tcc_add_file_internal(s, buf, 0) == 0)
10407 return 0;
10408 }
10409 return -1;
10410 }
10411
tcc_add_symbol(TCCState * s,const char * name,unsigned long val)10412 int tcc_add_symbol(TCCState *s, const char *name, unsigned long val)
10413 {
10414 add_elf_sym(symtab_section, val, 0,
10415 ELF32_ST_INFO(STB_GLOBAL, STT_NOTYPE), 0,
10416 SHN_ABS, name);
10417 return 0;
10418 }
10419
tcc_set_output_type(TCCState * s,int output_type)10420 int tcc_set_output_type(TCCState *s, int output_type)
10421 {
10422 char buf[1024];
10423
10424 s->output_type = output_type;
10425
10426 if (!s->nostdinc) {
10427 /* default include paths */
10428 /* XXX: reverse order needed if -isystem support */
10429 #ifndef TCC_TARGET_PE
10430 tcc_add_sysinclude_path(s, "/usr/local/include");
10431 tcc_add_sysinclude_path(s, "/usr/include");
10432 #endif
10433 snprintf(buf, sizeof(buf), "%s/include", tcc_lib_path);
10434 tcc_add_sysinclude_path(s, buf);
10435 #ifdef TCC_TARGET_PE
10436 snprintf(buf, sizeof(buf), "%s/include/winapi", tcc_lib_path);
10437 tcc_add_sysinclude_path(s, buf);
10438 #endif
10439 }
10440
10441 /* if bound checking, then add corresponding sections */
10442 #ifdef CONFIG_TCC_BCHECK
10443 if (do_bounds_check) {
10444 /* define symbol */
10445 tcc_define_symbol(s, "__BOUNDS_CHECKING_ON", NULL);
10446 /* create bounds sections */
10447 bounds_section = new_section(s, ".bounds",
10448 SHT_PROGBITS, SHF_ALLOC);
10449 lbounds_section = new_section(s, ".lbounds",
10450 SHT_PROGBITS, SHF_ALLOC);
10451 }
10452 #endif
10453
10454 if (s->char_is_unsigned) {
10455 tcc_define_symbol(s, "__CHAR_UNSIGNED__", NULL);
10456 }
10457
10458 /* add debug sections */
10459 if (do_debug) {
10460 /* stab symbols */
10461 stab_section = new_section(s, ".stab", SHT_PROGBITS, 0);
10462 stab_section->sh_entsize = sizeof(Stab_Sym);
10463 stabstr_section = new_section(s, ".stabstr", SHT_STRTAB, 0);
10464 put_elf_str(stabstr_section, "");
10465 stab_section->link = stabstr_section;
10466 /* put first entry */
10467 put_stabs("", 0, 0, 0, 0);
10468 }
10469
10470 /* add libc crt1/crti objects */
10471 #ifndef TCC_TARGET_PE
10472 if ((output_type == TCC_OUTPUT_EXE || output_type == TCC_OUTPUT_DLL) &&
10473 !s->nostdlib) {
10474 if (output_type != TCC_OUTPUT_DLL)
10475 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crt1.o");
10476 tcc_add_file(s, CONFIG_TCC_CRT_PREFIX "/crti.o");
10477 }
10478 #endif
10479
10480 #ifdef TCC_TARGET_PE
10481 snprintf(buf, sizeof(buf), "%s/lib", tcc_lib_path);
10482 tcc_add_library_path(s, buf);
10483 #endif
10484
10485 return 0;
10486 }
10487
10488 #define WD_ALL 0x0001 /* warning is activated when using -Wall */
10489 #define FD_INVERT 0x0002 /* invert value before storing */
10490
10491 typedef struct FlagDef {
10492 uint16_t offset;
10493 uint16_t flags;
10494 const char *name;
10495 } FlagDef;
10496
10497 static const FlagDef warning_defs[] = {
10498 { offsetof(TCCState, warn_unsupported), 0, "unsupported" },
10499 { offsetof(TCCState, warn_write_strings), 0, "write-strings" },
10500 { offsetof(TCCState, warn_error), 0, "error" },
10501 { offsetof(TCCState, warn_implicit_function_declaration), WD_ALL,
10502 "implicit-function-declaration" },
10503 };
10504
set_flag(TCCState * s,const FlagDef * flags,int nb_flags,const char * name,int value)10505 static int set_flag(TCCState *s, const FlagDef *flags, int nb_flags,
10506 const char *name, int value)
10507 {
10508 int i;
10509 const FlagDef *p;
10510 const char *r;
10511
10512 r = name;
10513 if (r[0] == 'n' && r[1] == 'o' && r[2] == '-') {
10514 r += 3;
10515 value = !value;
10516 }
10517 for(i = 0, p = flags; i < nb_flags; i++, p++) {
10518 if (!strcmp(r, p->name))
10519 goto found;
10520 }
10521 return -1;
10522 found:
10523 if (p->flags & FD_INVERT)
10524 value = !value;
10525 *(int *)((uint8_t *)s + p->offset) = value;
10526 return 0;
10527 }
10528
10529
10530 /* set/reset a warning */
tcc_set_warning(TCCState * s,const char * warning_name,int value)10531 int tcc_set_warning(TCCState *s, const char *warning_name, int value)
10532 {
10533 int i;
10534 const FlagDef *p;
10535
10536 if (!strcmp(warning_name, "all")) {
10537 for(i = 0, p = warning_defs; i < countof(warning_defs); i++, p++) {
10538 if (p->flags & WD_ALL)
10539 *(int *)((uint8_t *)s + p->offset) = 1;
10540 }
10541 return 0;
10542 } else {
10543 return set_flag(s, warning_defs, countof(warning_defs),
10544 warning_name, value);
10545 }
10546 }
10547
10548 static const FlagDef flag_defs[] = {
10549 { offsetof(TCCState, char_is_unsigned), 0, "unsigned-char" },
10550 { offsetof(TCCState, char_is_unsigned), FD_INVERT, "signed-char" },
10551 { offsetof(TCCState, nocommon), FD_INVERT, "common" },
10552 { offsetof(TCCState, leading_underscore), 0, "leading-underscore" },
10553 };
10554
10555 /* set/reset a flag */
tcc_set_flag(TCCState * s,const char * flag_name,int value)10556 int tcc_set_flag(TCCState *s, const char *flag_name, int value)
10557 {
10558 return set_flag(s, flag_defs, countof(flag_defs),
10559 flag_name, value);
10560 }
10561
10562 #if !defined(LIBTCC)
10563
getclock_us(void)10564 static int64_t getclock_us(void)
10565 {
10566 #ifdef _WIN32
10567 struct _timeb tb;
10568 _ftime(&tb);
10569 return (tb.time * 1000LL + tb.millitm) * 1000LL;
10570 #else
10571 struct timeval tv;
10572 gettimeofday(&tv, NULL);
10573 return tv.tv_sec * 1000000LL + tv.tv_usec;
10574 #endif
10575 }
10576
help(void)10577 void help(void)
10578 {
10579 printf("tcc version " TCC_VERSION " - Tiny C Compiler - Copyright (C) 2001-2006 Fabrice Bellard\n"
10580 "usage: tcc [-v] [-c] [-o outfile] [-Bdir] [-bench] [-Idir] [-Dsym[=val]] [-Usym]\n"
10581 " [-Wwarn] [-g] [-b] [-bt N] [-Ldir] [-llib] [-shared] [-soname name]\n"
10582 " [-static] [infile1 infile2...] [-run infile args...]\n"
10583 "\n"
10584 "General options:\n"
10585 " -v display current version, increase verbosity\n"
10586 " -c compile only - generate an object file\n"
10587 " -o outfile set output filename\n"
10588 " -Bdir set tcc internal library path\n"
10589 " -bench output compilation statistics\n"
10590 " -run run compiled source\n"
10591 " -fflag set or reset (with 'no-' prefix) 'flag' (see man page)\n"
10592 " -Wwarning set or reset (with 'no-' prefix) 'warning' (see man page)\n"
10593 " -w disable all warnings\n"
10594 "Preprocessor options:\n"
10595 " -E preprocess only\n"
10596 " -Idir add include path 'dir'\n"
10597 " -Dsym[=val] define 'sym' with value 'val'\n"
10598 " -Usym undefine 'sym'\n"
10599 "Linker options:\n"
10600 " -Ldir add library path 'dir'\n"
10601 " -llib link with dynamic or static library 'lib'\n"
10602 " -shared generate a shared library\n"
10603 " -soname set name for shared library to be used at runtime\n"
10604 " -static static linking\n"
10605 " -rdynamic export all global symbols to dynamic linker\n"
10606 " -r generate (relocatable) object file\n"
10607 "Debugger options:\n"
10608 " -g generate runtime debug info\n"
10609 #ifdef CONFIG_TCC_BCHECK
10610 " -b compile with built-in memory and bounds checker (implies -g)\n"
10611 #endif
10612 " -bt N show N callers in stack traces\n"
10613 );
10614 }
10615
10616 #define TCC_OPTION_HAS_ARG 0x0001
10617 #define TCC_OPTION_NOSEP 0x0002 /* cannot have space before option and arg */
10618
10619 typedef struct TCCOption {
10620 const char *name;
10621 uint16_t index;
10622 uint16_t flags;
10623 } TCCOption;
10624
10625 enum {
10626 TCC_OPTION_HELP,
10627 TCC_OPTION_I,
10628 TCC_OPTION_D,
10629 TCC_OPTION_U,
10630 TCC_OPTION_L,
10631 TCC_OPTION_B,
10632 TCC_OPTION_l,
10633 TCC_OPTION_bench,
10634 TCC_OPTION_bt,
10635 TCC_OPTION_b,
10636 TCC_OPTION_g,
10637 TCC_OPTION_c,
10638 TCC_OPTION_static,
10639 TCC_OPTION_shared,
10640 TCC_OPTION_soname,
10641 TCC_OPTION_o,
10642 TCC_OPTION_r,
10643 TCC_OPTION_Wl,
10644 TCC_OPTION_W,
10645 TCC_OPTION_O,
10646 TCC_OPTION_m,
10647 TCC_OPTION_f,
10648 TCC_OPTION_nostdinc,
10649 TCC_OPTION_nostdlib,
10650 TCC_OPTION_print_search_dirs,
10651 TCC_OPTION_rdynamic,
10652 TCC_OPTION_run,
10653 TCC_OPTION_v,
10654 TCC_OPTION_w,
10655 TCC_OPTION_pipe,
10656 TCC_OPTION_E,
10657 };
10658
10659 static const TCCOption tcc_options[] = {
10660 { "h", TCC_OPTION_HELP, 0 },
10661 { "?", TCC_OPTION_HELP, 0 },
10662 { "I", TCC_OPTION_I, TCC_OPTION_HAS_ARG },
10663 { "D", TCC_OPTION_D, TCC_OPTION_HAS_ARG },
10664 { "U", TCC_OPTION_U, TCC_OPTION_HAS_ARG },
10665 { "L", TCC_OPTION_L, TCC_OPTION_HAS_ARG },
10666 { "B", TCC_OPTION_B, TCC_OPTION_HAS_ARG },
10667 { "l", TCC_OPTION_l, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10668 { "bench", TCC_OPTION_bench, 0 },
10669 { "bt", TCC_OPTION_bt, TCC_OPTION_HAS_ARG },
10670 #ifdef CONFIG_TCC_BCHECK
10671 { "b", TCC_OPTION_b, 0 },
10672 #endif
10673 { "g", TCC_OPTION_g, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10674 { "c", TCC_OPTION_c, 0 },
10675 { "static", TCC_OPTION_static, 0 },
10676 { "shared", TCC_OPTION_shared, 0 },
10677 { "soname", TCC_OPTION_soname, TCC_OPTION_HAS_ARG },
10678 { "o", TCC_OPTION_o, TCC_OPTION_HAS_ARG },
10679 { "run", TCC_OPTION_run, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10680 { "rdynamic", TCC_OPTION_rdynamic, 0 },
10681 { "r", TCC_OPTION_r, 0 },
10682 { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10683 { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10684 { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10685 { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
10686 { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10687 { "nostdinc", TCC_OPTION_nostdinc, 0 },
10688 { "nostdlib", TCC_OPTION_nostdlib, 0 },
10689 { "print-search-dirs", TCC_OPTION_print_search_dirs, 0 },
10690 { "v", TCC_OPTION_v, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
10691 { "w", TCC_OPTION_w, 0 },
10692 { "pipe", TCC_OPTION_pipe, 0},
10693 { "E", TCC_OPTION_E, 0},
10694 { NULL },
10695 };
10696
10697 /* convert 'str' into an array of space separated strings */
expand_args(char *** pargv,const char * str)10698 static int expand_args(char ***pargv, const char *str)
10699 {
10700 const char *s1;
10701 char **argv, *arg;
10702 int argc, len;
10703
10704 argc = 0;
10705 argv = NULL;
10706 for(;;) {
10707 while (is_space(*str))
10708 str++;
10709 if (*str == '\0')
10710 break;
10711 s1 = str;
10712 while (*str != '\0' && !is_space(*str))
10713 str++;
10714 len = str - s1;
10715 arg = tcc_malloc(len + 1);
10716 memcpy(arg, s1, len);
10717 arg[len] = '\0';
10718 dynarray_add((void ***)&argv, &argc, arg);
10719 }
10720 *pargv = argv;
10721 return argc;
10722 }
10723
10724 static char **files;
10725 static int nb_files, nb_libraries;
10726 static int multiple_files;
10727 static int print_search_dirs;
10728 static int output_type;
10729 static int reloc_output;
10730 static const char *outfile;
10731
parse_args(TCCState * s,int argc,char ** argv)10732 int parse_args(TCCState *s, int argc, char **argv)
10733 {
10734 int optind;
10735 const TCCOption *popt;
10736 const char *optarg, *p1, *r1;
10737 char *r;
10738
10739 optind = 0;
10740 while (1) {
10741 if (optind >= argc) {
10742 if (nb_files == 0 && !print_search_dirs) {
10743 if (verbose)
10744 exit(0);
10745 goto show_help;
10746 }
10747 break;
10748 }
10749 r = argv[optind++];
10750 if (r[0] != '-' || r[1] == '\0') {
10751 /* add a new file */
10752 dynarray_add((void ***)&files, &nb_files, r);
10753 if (!multiple_files) {
10754 optind--;
10755 /* argv[0] will be this file */
10756 break;
10757 }
10758 } else {
10759 /* find option in table (match only the first chars */
10760 popt = tcc_options;
10761 for(;;) {
10762 p1 = popt->name;
10763 if (p1 == NULL)
10764 error("invalid option -- '%s'", r);
10765 r1 = r + 1;
10766 for(;;) {
10767 if (*p1 == '\0')
10768 goto option_found;
10769 if (*r1 != *p1)
10770 break;
10771 p1++;
10772 r1++;
10773 }
10774 popt++;
10775 }
10776 option_found:
10777 if (popt->flags & TCC_OPTION_HAS_ARG) {
10778 if (*r1 != '\0' || (popt->flags & TCC_OPTION_NOSEP)) {
10779 optarg = r1;
10780 } else {
10781 if (optind >= argc)
10782 error("argument to '%s' is missing", r);
10783 optarg = argv[optind++];
10784 }
10785 } else {
10786 if (*r1 != '\0')
10787 goto show_help;
10788 optarg = NULL;
10789 }
10790
10791 switch(popt->index) {
10792 case TCC_OPTION_HELP:
10793 show_help:
10794 help();
10795 exit(1);
10796 case TCC_OPTION_I:
10797 if (tcc_add_include_path(s, optarg) < 0)
10798 error("too many include paths");
10799 break;
10800 case TCC_OPTION_D:
10801 {
10802 char *sym, *value;
10803 sym = (char *)optarg;
10804 value = strchr(sym, '=');
10805 if (value) {
10806 *value = '\0';
10807 value++;
10808 }
10809 tcc_define_symbol(s, sym, value);
10810 }
10811 break;
10812 case TCC_OPTION_U:
10813 tcc_undefine_symbol(s, optarg);
10814 break;
10815 case TCC_OPTION_L:
10816 tcc_add_library_path(s, optarg);
10817 break;
10818 case TCC_OPTION_B:
10819 /* set tcc utilities path (mainly for tcc development) */
10820 strcpy(tcc_lib_path, optarg);
10821 break;
10822 case TCC_OPTION_l:
10823 dynarray_add((void ***)&files, &nb_files, r);
10824 nb_libraries++;
10825 break;
10826 case TCC_OPTION_bench:
10827 do_bench = 1;
10828 break;
10829 case TCC_OPTION_bt:
10830 num_callers = atoi(optarg);
10831 break;
10832 #ifdef CONFIG_TCC_BCHECK
10833 case TCC_OPTION_b:
10834 do_bounds_check = 1;
10835 do_debug = 1;
10836 break;
10837 #endif
10838 case TCC_OPTION_g:
10839 do_debug = 1;
10840 break;
10841 case TCC_OPTION_c:
10842 multiple_files = 1;
10843 output_type = TCC_OUTPUT_OBJ;
10844 break;
10845 case TCC_OPTION_static:
10846 s->static_link = 1;
10847 break;
10848 case TCC_OPTION_shared:
10849 output_type = TCC_OUTPUT_DLL;
10850 break;
10851 case TCC_OPTION_soname:
10852 s->soname = optarg;
10853 break;
10854 case TCC_OPTION_o:
10855 multiple_files = 1;
10856 outfile = optarg;
10857 break;
10858 case TCC_OPTION_r:
10859 /* generate a .o merging several output files */
10860 reloc_output = 1;
10861 output_type = TCC_OUTPUT_OBJ;
10862 break;
10863 case TCC_OPTION_nostdinc:
10864 s->nostdinc = 1;
10865 break;
10866 case TCC_OPTION_nostdlib:
10867 s->nostdlib = 1;
10868 break;
10869 case TCC_OPTION_print_search_dirs:
10870 print_search_dirs = 1;
10871 break;
10872 case TCC_OPTION_run:
10873 {
10874 int argc1;
10875 char **argv1;
10876 argc1 = expand_args(&argv1, optarg);
10877 if (argc1 > 0) {
10878 parse_args(s, argc1, argv1);
10879 }
10880 multiple_files = 0;
10881 output_type = TCC_OUTPUT_MEMORY;
10882 }
10883 break;
10884 case TCC_OPTION_v:
10885 do {
10886 if (0 == verbose++)
10887 printf("tcc version %s\n", TCC_VERSION);
10888 } while (*optarg++ == 'v');
10889 break;
10890 case TCC_OPTION_f:
10891 if (tcc_set_flag(s, optarg, 1) < 0 && s->warn_unsupported)
10892 goto unsupported_option;
10893 break;
10894 case TCC_OPTION_W:
10895 if (tcc_set_warning(s, optarg, 1) < 0 &&
10896 s->warn_unsupported)
10897 goto unsupported_option;
10898 break;
10899 case TCC_OPTION_w:
10900 s->warn_none = 1;
10901 break;
10902 case TCC_OPTION_rdynamic:
10903 s->rdynamic = 1;
10904 break;
10905 case TCC_OPTION_Wl:
10906 {
10907 const char *p;
10908 if (strstart(optarg, "-Ttext,", &p)) {
10909 s->text_addr = strtoul(p, NULL, 16);
10910 s->has_text_addr = 1;
10911 } else if (strstart(optarg, "--oformat,", &p)) {
10912 if (strstart(p, "elf32-", NULL)) {
10913 s->output_format = TCC_OUTPUT_FORMAT_ELF;
10914 } else if (!strcmp(p, "binary")) {
10915 s->output_format = TCC_OUTPUT_FORMAT_BINARY;
10916 } else
10917 #ifdef TCC_TARGET_COFF
10918 if (!strcmp(p, "coff")) {
10919 s->output_format = TCC_OUTPUT_FORMAT_COFF;
10920 } else
10921 #endif
10922 {
10923 error("target %s not found", p);
10924 }
10925 } else {
10926 error("unsupported linker option '%s'", optarg);
10927 }
10928 }
10929 break;
10930 case TCC_OPTION_E:
10931 output_type = TCC_OUTPUT_PREPROCESS;
10932 break;
10933 default:
10934 if (s->warn_unsupported) {
10935 unsupported_option:
10936 warning("unsupported option '%s'", r);
10937 }
10938 break;
10939 }
10940 }
10941 }
10942 return optind;
10943 }
10944
main(int argc,char ** argv)10945 int main(int argc, char **argv)
10946 {
10947 int i;
10948 TCCState *s;
10949 int nb_objfiles, ret, optind;
10950 char objfilename[1024];
10951 int64_t start_time = 0;
10952
10953 #ifdef _WIN32
10954 strcpy(tcc_lib_path, w32_tcc_lib_path());
10955 #endif
10956
10957 s = tcc_new();
10958 output_type = TCC_OUTPUT_EXE;
10959 outfile = NULL;
10960 multiple_files = 1;
10961 files = NULL;
10962 nb_files = 0;
10963 nb_libraries = 0;
10964 reloc_output = 0;
10965 print_search_dirs = 0;
10966 ret = 0;
10967
10968 optind = parse_args(s, argc - 1, argv + 1) + 1;
10969
10970 if (print_search_dirs) {
10971 /* enough for Linux kernel */
10972 printf("install: %s/\n", tcc_lib_path);
10973 return 0;
10974 }
10975
10976 nb_objfiles = nb_files - nb_libraries;
10977
10978 /* if outfile provided without other options, we output an
10979 executable */
10980 if (outfile && output_type == TCC_OUTPUT_MEMORY)
10981 output_type = TCC_OUTPUT_EXE;
10982
10983 /* check -c consistency : only single file handled. XXX: checks file type */
10984 if (output_type == TCC_OUTPUT_OBJ && !reloc_output) {
10985 /* accepts only a single input file */
10986 if (nb_objfiles != 1)
10987 error("cannot specify multiple files with -c");
10988 if (nb_libraries != 0)
10989 error("cannot specify libraries with -c");
10990 }
10991
10992
10993 if (output_type == TCC_OUTPUT_PREPROCESS) {
10994 if (!outfile) {
10995 s->outfile = stdout;
10996 } else {
10997 s->outfile = fopen(outfile, "w");
10998 if (!s->outfile)
10999 error("could not open '%s", outfile);
11000 }
11001 } else if (output_type != TCC_OUTPUT_MEMORY) {
11002 if (!outfile) {
11003 /* compute default outfile name */
11004 char *ext;
11005 const char *name =
11006 strcmp(files[0], "-") == 0 ? "a" : tcc_basename(files[0]);
11007 pstrcpy(objfilename, sizeof(objfilename), name);
11008 ext = tcc_fileextension(objfilename);
11009 #ifdef TCC_TARGET_PE
11010 if (output_type == TCC_OUTPUT_DLL)
11011 strcpy(ext, ".dll");
11012 else
11013 if (output_type == TCC_OUTPUT_EXE)
11014 strcpy(ext, ".exe");
11015 else
11016 #endif
11017 if (output_type == TCC_OUTPUT_OBJ && !reloc_output && *ext)
11018 strcpy(ext, ".o");
11019 else
11020 pstrcpy(objfilename, sizeof(objfilename), "a.out");
11021 outfile = objfilename;
11022 }
11023 }
11024
11025 if (do_bench) {
11026 start_time = getclock_us();
11027 }
11028
11029 tcc_set_output_type(s, output_type);
11030
11031 /* compile or add each files or library */
11032 for(i = 0; i < nb_files && ret == 0; i++) {
11033 const char *filename;
11034
11035 filename = files[i];
11036 if (output_type == TCC_OUTPUT_PREPROCESS) {
11037 if (tcc_add_file_internal(s, filename,
11038 AFF_PRINT_ERROR | AFF_PREPROCESS) < 0)
11039 ret = 1;
11040 } else if (filename[0] == '-' && filename[1]) {
11041 if (tcc_add_library(s, filename + 2) < 0)
11042 error("cannot find %s", filename);
11043 } else {
11044 if (1 == verbose)
11045 printf("-> %s\n", filename);
11046 if (tcc_add_file(s, filename) < 0)
11047 ret = 1;
11048 }
11049 }
11050
11051 /* free all files */
11052 tcc_free(files);
11053
11054 if (ret)
11055 goto the_end;
11056
11057 if (do_bench) {
11058 double total_time;
11059 total_time = (double)(getclock_us() - start_time) / 1000000.0;
11060 if (total_time < 0.001)
11061 total_time = 0.001;
11062 if (total_bytes < 1)
11063 total_bytes = 1;
11064 printf("%d idents, %d lines, %d bytes, %0.3f s, %d lines/s, %0.1f MB/s\n",
11065 tok_ident - TOK_IDENT, total_lines, total_bytes,
11066 total_time, (int)(total_lines / total_time),
11067 total_bytes / total_time / 1000000.0);
11068 }
11069
11070 if (s->output_type == TCC_OUTPUT_PREPROCESS) {
11071 if (outfile)
11072 fclose(s->outfile);
11073 } else if (s->output_type == TCC_OUTPUT_MEMORY) {
11074 ret = tcc_run(s, argc - optind, argv + optind);
11075 } else
11076 #ifdef TCC_TARGET_PE
11077 if (s->output_type != TCC_OUTPUT_OBJ) {
11078 ret = pe_output_file(s, outfile);
11079 } else
11080 #endif
11081 {
11082 ret = tcc_output_file(s, outfile) ? 1 : 0;
11083 }
11084 the_end:
11085 /* XXX: cannot do it with bound checking because of the malloc hooks */
11086 if (!do_bounds_check)
11087 tcc_delete(s);
11088
11089 #ifdef MEM_DEBUG
11090 if (do_bench) {
11091 printf("memory: %d bytes, max = %d bytes\n", mem_cur_size, mem_max_size);
11092 }
11093 #endif
11094 return ret;
11095 }
11096
11097 #endif
11098