2 * TCC - Tiny C Compiler
4 * Copyright (c) 2001 Fabrice Bellard
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program 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
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #ifndef CONFIG_TCC_STATIC
30 /* preprocessor debug */
33 /* these sizes are dummy for unix, because malloc() does not use
34 memory when the pages are not used */
35 #define TEXT_SIZE (4*1024*1024)
36 #define DATA_SIZE (4*1024*1024)
38 #define INCLUDE_STACK_SIZE 32
39 #define IFDEF_STACK_SIZE 64
40 #define VSTACK_SIZE 64
41 #define STRING_MAX_SIZE 1024
42 #define INCLUDE_PATHS_MAX 32
44 #define TOK_HASH_SIZE 521
45 #define TOK_ALLOC_INCR 256 /* must be a power of two */
46 #define SYM_HASH_SIZE 263
48 /* token symbol management */
49 typedef struct TokenSym
{
50 struct TokenSym
*hash_next
;
51 int tok
; /* token number */
57 typedef union CValue
{
63 unsigned int ul
; /* address (should be unsigned long on 64 bit cpu) */
65 unsigned long long ull
;
72 typedef struct SValue
{
74 int r
; /* register + flags */
75 CValue c
; /* constant */
78 /* symbol management */
80 int v
; /* symbol token */
81 int t
; /* associated type */
82 int c
; /* associated number */
83 struct Sym
*next
; /* next related symbol */
84 struct Sym
*prev
; /* prev symbol in stack */
85 struct Sym
*hash_next
; /* next symbol in hash table */
88 typedef struct SymStack
{
90 struct Sym
*hash
[SYM_HASH_SIZE
];
93 /* relocation entry (currently only used for functions or variables */
94 typedef struct Reloc
{
95 int type
; /* type of relocation */
96 int addr
; /* address of relocation */
97 struct Reloc
*next
; /* next relocation */
100 #define RELOC_ADDR32 1 /* 32 bits relocation */
101 #define RELOC_REL32 2 /* 32 bits relative relocation */
104 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
105 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
106 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
108 #define FUNC_NEW 1 /* ansi function prototype */
109 #define FUNC_OLD 2 /* old function prototype */
110 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
112 /* field 'Sym.t' for macros */
113 #define MACRO_OBJ 0 /* object like macro */
114 #define MACRO_FUNC 1 /* function like macro */
116 /* type_decl() types */
117 #define TYPE_ABSTRACT 1 /* type without variable */
118 #define TYPE_DIRECT 2 /* type with variable */
129 int ch
, ch1
, tok
, tok1
;
132 /* loc : local variable index
133 glo : global variable index
134 ind : output code ptr
137 anon_sym: anonymous symbol index
140 prog
, ind
, loc
, glo
, const_wanted
;
141 int global_expr
; /* true if compound literals must be allocated
142 globally (used during initializers parsing */
143 int func_vt
, func_vc
; /* current function return type (used by
144 return instruction) */
146 TokenSym
**table_ident
;
147 TokenSym
*hash_ident
[TOK_HASH_SIZE
];
148 char token_buf
[STRING_MAX_SIZE
+ 1];
149 char *filename
, *funcname
;
150 /* contains global symbols which remain between each translation unit */
151 SymStack extern_stack
;
152 SymStack define_stack
, global_stack
, local_stack
, label_stack
;
154 SValue vstack
[VSTACK_SIZE
], *vtop
;
155 int *macro_ptr
, *macro_ptr_allocated
;
156 IncludeFile include_stack
[INCLUDE_STACK_SIZE
], *include_stack_ptr
;
157 int ifdef_stack
[IFDEF_STACK_SIZE
], *ifdef_stack_ptr
;
158 char *include_paths
[INCLUDE_PATHS_MAX
];
159 int nb_include_paths
;
161 /* use GNU C extensions */
164 /* use Tiny C extensions */
167 /* The current value can be: */
168 #define VT_VALMASK 0x000f
169 #define VT_CONST 0x000a /* constant in vc
170 (must be first non register value) */
171 #define VT_LLOCAL 0x000b /* lvalue, offset on stack */
172 #define VT_LOCAL 0x000c /* offset on stack */
173 #define VT_CMP 0x000d /* the value is stored in processor flags (in vc) */
174 #define VT_JMP 0x000e /* value is the consequence of jmp true */
175 #define VT_JMPI 0x000f /* value is the consequence of jmp false */
176 #define VT_LVAL 0x0010 /* var is an lvalue */
177 #define VT_LVALN -17 /* ~VT_LVAL */
178 #define VT_FORWARD 0x0020 /* value is forward reference
179 (only used for functions) */
181 #define VT_EXTERN 0x00000040 /* extern definition */
182 #define VT_STATIC 0x00000080 /* static variable */
183 #define VT_TYPEDEF 0x00000100 /* typedef definition */
186 #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
188 #define VT_BTYPE_SHIFT 9
189 #define VT_INT (0 << VT_BTYPE_SHIFT) /* integer type */
190 #define VT_BYTE (1 << VT_BTYPE_SHIFT) /* signed byte type */
191 #define VT_SHORT (2 << VT_BTYPE_SHIFT) /* short type */
192 #define VT_VOID (3 << VT_BTYPE_SHIFT) /* void type */
193 #define VT_PTR (4 << VT_BTYPE_SHIFT) /* pointer increment */
194 #define VT_ENUM (5 << VT_BTYPE_SHIFT) /* enum definition */
195 #define VT_FUNC (6 << VT_BTYPE_SHIFT) /* function type */
196 #define VT_STRUCT (7 << VT_BTYPE_SHIFT) /* struct/union definition */
197 #define VT_FLOAT (8 << VT_BTYPE_SHIFT) /* IEEE float */
198 #define VT_DOUBLE (9 << VT_BTYPE_SHIFT) /* IEEE double */
199 #define VT_LDOUBLE (10 << VT_BTYPE_SHIFT) /* IEEE long double */
200 #define VT_BOOL (11 << VT_BTYPE_SHIFT) /* ISOC99 boolean type */
201 #define VT_LLONG (12 << VT_BTYPE_SHIFT) /* 64 bit integer */
202 #define VT_LONG (13 << VT_BTYPE_SHIFT) /* long integer (NEVER
205 #define VT_BTYPE (0xf << VT_BTYPE_SHIFT) /* mask for basic type */
206 #define VT_UNSIGNED (0x10 << VT_BTYPE_SHIFT) /* unsigned type */
207 #define VT_ARRAY (0x20 << VT_BTYPE_SHIFT) /* array type (also has VT_PTR) */
208 #define VT_BITFIELD (0x40 << VT_BTYPE_SHIFT) /* bitfield modifier */
210 #define VT_TYPE 0xfffffe00 /* type mask */
214 /* warning: the following compare tokens depend on i386 asm code */
226 #define TOK_LAND 0xa0
230 #define TOK_MID 0xa3 /* inc/dec, to void constant */
232 #define TOK_ARROW 0xa7
233 #define TOK_DOTS 0xa8 /* three dots */
234 #define TOK_SHR 0xa9 /* unsigned shift right */
235 #define TOK_UDIV 0xb0 /* unsigned division */
236 #define TOK_UMOD 0xb1 /* unsigned modulo */
237 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
238 #define TOK_NUM 0xb3 /* number in tokc */
239 #define TOK_CCHAR 0xb4 /* char constant in tokc */
240 #define TOK_STR 0xb5 /* pointer to string in tokc */
241 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
242 #define TOK_LCHAR 0xb7
243 #define TOK_LSTR 0xb8
244 #define TOK_CFLOAT 0xb9 /* float constant */
245 #define TOK_CDOUBLE 0xc0 /* double constant */
246 #define TOK_CLDOUBLE 0xc1 /* long double constant */
248 #define TOK_SHL 0x01 /* shift left */
249 #define TOK_SAR 0x02 /* signed shift right */
251 /* assignement operators : normal operator or 0x80 */
252 #define TOK_A_MOD 0xa5
253 #define TOK_A_AND 0xa6
254 #define TOK_A_MUL 0xaa
255 #define TOK_A_ADD 0xab
256 #define TOK_A_SUB 0xad
257 #define TOK_A_DIV 0xaf
258 #define TOK_A_XOR 0xde
259 #define TOK_A_OR 0xfc
260 #define TOK_A_SHL 0x81
261 #define TOK_A_SAR 0x82
263 /* all identificators and strings have token above that */
264 #define TOK_IDENT 256
285 /* ignored types Must have contiguous values */
295 /* unsupported type */
308 /* preprocessor only */
309 TOK_UIDENT
, /* first "user" ident (not keyword) */
310 TOK_DEFINE
= TOK_UIDENT
,
326 /* special identifiers */
331 /* XXX: need to define this to use them in non ISOC99 context */
332 extern float strtof (const char *__nptr
, char **__endptr
);
333 extern long double strtold (const char *__nptr
, char **__endptr
);
337 void next_nomacro(void);
338 int expr_const(void);
342 void decl_initializer(int t
, int c
, int first
, int size_only
);
343 int decl_initializer_alloc(int t
, int has_init
);
345 void move_reg(int r
, int s
);
346 void save_reg(int r
);
352 void macro_subst(int **tok_str
, int *tok_len
,
353 Sym
**nested_list
, int *macro_str
);
354 int save_reg_forced(int r
);
356 void gen_cast(int t
);
358 int type_size(int t
, int *a
);
359 int pointed_type(int t
);
360 int pointed_size(int t
);
362 int type_decl(int *v
, int t
, int td
);
363 void error(const char *fmt
, ...);
364 void vset(int t
, int r
, int v
);
366 /* true if float/double/long double type */
367 static inline int is_float(int t
)
371 return bt
== VT_LDOUBLE
|| bt
== VT_DOUBLE
|| bt
== VT_FLOAT
;
374 #include "i386-gen.c"
376 #ifdef CONFIG_TCC_STATIC
378 #define RTLD_LAZY 0x001
379 #define RTLD_NOW 0x002
380 #define RTLD_GLOBAL 0x100
382 /* dummy function for profiling */
383 void *dlopen(const char *filename
, int flag
)
388 const char *dlerror(void)
393 typedef struct TCCSyms
{
398 #define TCCSYM(a) { #a, &a, },
400 /* add the symbol you want here if no dynamic linking is done */
401 static TCCSyms tcc_syms
[] = {
409 void *dlsym(void *handle
, char *symbol
)
413 while (p
->str
!= NULL
) {
414 if (!strcmp(p
->str
, symbol
))
423 static inline int isid(int c
)
425 return (c
>= 'a' && c
<= 'z') ||
426 (c
>= 'A' && c
<= 'Z') ||
430 static inline int isnum(int c
)
432 return c
>= '0' & c
<= '9';
435 static inline int toup(int c
)
437 if (ch
>= 'a' && ch
<= 'z')
438 return ch
- 'a' + 'A';
446 for(f
= include_stack
; f
< include_stack_ptr
; f
++)
447 fprintf(stderr
, "In file included from %s:%d:\n",
448 f
->filename
, f
->line_num
);
449 fprintf(stderr
, "%s:%d: ", filename
, line_num
);
452 void error(const char *fmt
, ...)
457 vfprintf(stderr
, fmt
, ap
);
458 fprintf(stderr
, "\n");
463 void expect(const char *msg
)
465 error("%s expected", msg
);
468 void warning(const char *fmt
, ...)
474 fprintf(stderr
, "warning: ");
475 vfprintf(stderr
, fmt
, ap
);
476 fprintf(stderr
, "\n");
483 error("'%c' expected", c
);
487 void test_lvalue(void)
489 if (!(vtop
->r
& VT_LVAL
))
493 TokenSym
*tok_alloc(char *str
, int len
)
495 TokenSym
*ts
, **pts
, **ptable
;
502 h
= ((h
<< 8) | (str
[i
] & 0xff)) % TOK_HASH_SIZE
;
504 pts
= &hash_ident
[h
];
509 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
511 pts
= &(ts
->hash_next
);
514 if (tok_ident
>= SYM_FIRST_ANOM
)
515 error("memory full");
517 /* expand token table if needed */
518 i
= tok_ident
- TOK_IDENT
;
519 if ((i
% TOK_ALLOC_INCR
) == 0) {
520 ptable
= realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
522 error("memory full");
523 table_ident
= ptable
;
526 ts
= malloc(sizeof(TokenSym
) + len
);
528 error("memory full");
530 ts
->tok
= tok_ident
++;
532 ts
->hash_next
= NULL
;
533 memcpy(ts
->str
, str
, len
+ 1);
538 void add_char(char **pp
, int c
)
542 if (c
== '\'' || c
== '\"' || c
== '\\') {
543 /* XXX: could be more precise if char or string */
546 if (c
>= 32 && c
<= 126) {
553 *p
++ = '0' + ((c
>> 6) & 7);
554 *p
++ = '0' + ((c
>> 3) & 7);
555 *p
++ = '0' + (c
& 7);
561 /* XXX: buffer overflow */
562 char *get_tok_str(int v
, CValue
*cv
)
564 static char buf
[STRING_MAX_SIZE
+ 1];
570 sprintf(buf
, "%u", cv
->ui
);
572 } else if (v
== TOK_CCHAR
|| v
== TOK_LCHAR
) {
579 } else if (v
== TOK_STR
|| v
== TOK_LSTR
) {
583 for(i
=0;i
<ts
->len
;i
++)
584 add_char(&p
, ts
->str
[i
]);
588 } else if (v
< TOK_IDENT
) {
593 } else if (v
< tok_ident
) {
594 return table_ident
[v
- TOK_IDENT
]->str
;
596 /* should never happen */
601 /* push, without hashing */
602 Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
605 s
= malloc(sizeof(Sym
));
607 error("memory full");
618 /* find a symbol and return its associated structure. 's' is the top
619 of the symbol stack */
620 Sym
*sym_find2(Sym
*s
, int v
)
630 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
632 /* find a symbol and return its associated structure. 'st' is the
634 Sym
*sym_find1(SymStack
*st
, int v
)
638 s
= st
->hash
[HASH_SYM(v
)];
647 Sym
*sym_push1(SymStack
*st
, int v
, int t
, int c
)
650 s
= sym_push2(&st
->top
, v
, t
, c
);
651 /* add in hash table */
653 ps
= &st
->hash
[HASH_SYM(v
)];
660 /* find a symbol in the right symbol space */
664 s
= sym_find1(&local_stack
, v
);
666 s
= sym_find1(&global_stack
, v
);
670 /* push a given symbol on the symbol stack */
671 Sym
*sym_push(int v
, int t
, int c
)
674 return sym_push1(&local_stack
, v
, t
, c
);
676 return sym_push1(&global_stack
, v
, t
, c
);
679 /* pop symbols until top reaches 'b' */
680 void sym_pop(SymStack
*st
, Sym
*b
)
687 /* free hash table entry, except if symbol was freed (only
688 used for #undef symbols) */
690 st
->hash
[HASH_SYM(s
->v
)] = s
->hash_next
;
697 /* undefined a hashed symbol (used for #undef). Its name is set to
699 void sym_undef(SymStack
*st
, Sym
*s
)
702 ss
= &st
->hash
[HASH_SYM(s
->v
)];
703 while (*ss
!= NULL
) {
706 ss
= &(*ss
)->hash_next
;
712 /* no need to put that inline */
715 if (include_stack_ptr
== include_stack
)
717 /* pop include stack */
721 file
= include_stack_ptr
->file
;
722 filename
= include_stack_ptr
->filename
;
723 line_num
= include_stack_ptr
->line_num
;
727 /* read next char from current input file */
728 static inline void inp(void)
731 /* faster than fgetc */
732 ch1
= getc_unlocked(file
);
734 if (handle_eof() < 0)
741 // printf("ch1=%c 0x%x\n", ch1, ch1);
744 /* input with '\\n' handling */
745 static inline void minp(void)
750 if (ch
== '\\' && ch1
== '\n') {
754 //printf("ch=%c 0x%x\n", ch, ch);
758 /* same as minp, but also skip comments */
766 /* single line C++ comments */
768 while (ch1
!= '\n' && ch1
!= -1)
771 ch
= ' '; /* return space */
772 } else if (ch1
== '*') {
778 if (c
== '*' && ch1
== '/') {
780 ch
= ' '; /* return space */
792 void skip_spaces(void)
794 while (ch
== ' ' || ch
== '\t')
798 /* skip block of text until #else, #elif or #endif. skip also pairs of
800 void preprocess_skip()
816 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
818 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
820 else if (tok
== TOK_ENDIF
)
826 /* return the number of additionnal 'ints' necessary to store the
828 static inline int tok_ext_size(int t
)
842 return LDOUBLE_SIZE
/ 4;
848 void tok_add(int **tok_str
, int *tok_len
, int t
)
853 if ((len
& 63) == 0) {
854 str
= realloc(str
, (len
+ 64) * sizeof(int));
863 void tok_add2(int **tok_str
, int *tok_len
, int t
, CValue
*cv
)
867 tok_add(tok_str
, tok_len
, t
);
870 tok_add(tok_str
, tok_len
, cv
->tab
[i
]);
873 /* get a token from an integer array and increment pointer accordingly */
874 int tok_get(int **tok_str
, CValue
*cv
)
887 /* eval an expression for #if/#elif */
888 int expr_preprocess(void)
898 next(); /* do macro subst */
899 if (tok
== TOK_DEFINED
) {
904 c
= sym_find1(&define_stack
, tok
) != 0;
909 } else if (tok
>= TOK_IDENT
) {
910 /* if undefined macro */
914 tok_add2(&str
, &len
, tok
, &tokc
);
916 tok_add(&str
, &len
, -1); /* simulate end of file */
917 tok_add(&str
, &len
, 0);
918 /* now evaluate C constant expression */
928 void tok_print(int *str
)
934 t
= tok_get(&str
, &cval
);
937 printf(" %s", get_tok_str(t
, &cval
));
943 /* XXX: should be more factorized */
944 void define_symbol(char *sym
)
950 ts
= tok_alloc(sym
, 0);
954 tok_add2(&str
, &len
, TOK_NUM
, &cval
);
955 tok_add(&str
, &len
, 0);
956 sym_push1(&define_stack
, ts
->tok
, MACRO_OBJ
, (int)str
);
959 void preprocess(void)
961 int size
, i
, c
, v
, t
, *str
, len
;
962 char buf
[1024], *q
, *p
;
965 Sym
**ps
, *first
, *s
;
970 if (tok
== TOK_DEFINE
) {
973 /* XXX: should check if same macro (ANSI) */
976 /* '(' must be just after macro definition for MACRO_FUNC */
983 tok
= TOK___VA_ARGS__
;
984 s
= sym_push1(&define_stack
, tok
| SYM_FIELD
, 0, 0);
998 if (ch
== '\n' || ch
== -1)
1001 tok_add2(&str
, &len
, tok
, &tokc
);
1003 tok_add(&str
, &len
, 0);
1005 printf("define %s %d: ", get_tok_str(v
, NULL
), t
);
1008 s
= sym_push1(&define_stack
, v
, t
, (int)str
);
1010 } else if (tok
== TOK_UNDEF
) {
1012 s
= sym_find1(&define_stack
, tok
);
1013 /* undefine symbol by putting an invalid name */
1015 sym_undef(&define_stack
, s
);
1016 } else if (tok
== TOK_INCLUDE
) {
1021 } else if (ch
== '\"') {
1026 while (ch
!= c
&& ch
!= '\n' && ch
!= -1) {
1027 if ((q
- buf
) < sizeof(buf
) - 1)
1035 error("#include syntax error");
1036 /* XXX: buffer overflow */
1037 strcpy(buf
, get_tok_str(tok
, &tokc
));
1040 /* eat all spaces and comments after include */
1041 /* XXX: slightly incorrect */
1042 while (ch1
!= '\n' && ch1
!= -1)
1045 if (include_stack_ptr
>= include_stack
+ INCLUDE_STACK_SIZE
)
1046 error("memory full");
1048 /* first search in current dir if "header.h" */
1049 /* XXX: buffer overflow */
1051 p
= strrchr(filename
, '/');
1053 size
= p
+ 1 - filename
;
1054 memcpy(buf1
, filename
, size
);
1057 f
= fopen(buf1
, "r");
1061 /* now search in standard include path */
1062 for(i
=nb_include_paths
- 1;i
>=0;i
--) {
1063 strcpy(buf1
, include_paths
[i
]);
1066 f
= fopen(buf1
, "r");
1070 error("include file '%s' not found", buf1
);
1073 /* push current file in stack */
1074 /* XXX: fix current line init */
1075 include_stack_ptr
->file
= file
;
1076 include_stack_ptr
->filename
= filename
;
1077 include_stack_ptr
->line_num
= line_num
;
1078 include_stack_ptr
++;
1080 filename
= strdup(buf1
);
1082 } else if (tok
== TOK_IFNDEF
) {
1085 } else if (tok
== TOK_IF
) {
1086 c
= expr_preprocess();
1088 } else if (tok
== TOK_IFDEF
) {
1092 c
= (sym_find1(&define_stack
, tok
) != 0) ^ c
;
1094 if (ifdef_stack_ptr
>= ifdef_stack
+ IFDEF_STACK_SIZE
)
1095 error("memory full");
1096 *ifdef_stack_ptr
++ = c
;
1098 } else if (tok
== TOK_ELSE
) {
1099 if (ifdef_stack_ptr
== ifdef_stack
||
1100 (ifdef_stack_ptr
[-1] & 2))
1101 error("#else after #else");
1102 c
= (ifdef_stack_ptr
[-1] ^= 3);
1104 } else if (tok
== TOK_ELIF
) {
1105 if (ifdef_stack_ptr
== ifdef_stack
||
1106 ifdef_stack_ptr
[-1] > 1)
1107 error("#elif after #else");
1108 c
= expr_preprocess();
1109 ifdef_stack_ptr
[-1] = c
;
1115 } else if (tok
== TOK_ENDIF
) {
1116 if (ifdef_stack_ptr
== ifdef_stack
)
1119 } else if (tok
== TOK_LINE
) {
1129 /* XXX: potential memory leak */
1130 filename
= strdup(get_tok_str(tok
, &tokc
));
1132 } else if (tok
== TOK_ERROR
) {
1135 /* ignore other preprocess commands or #! for C scripts */
1136 while (ch
!= '\n' && ch
!= -1)
1140 /* read a number in base b */
1146 if (ch
>= 'a' & ch
<= 'f')
1148 else if (ch
>= 'A' & ch
<= 'F')
1162 /* read a character for string or char constant and eval escape codes */
1171 /* at most three octal digits */
1175 c
= c
* 8 + ch
- '0';
1178 c
= c
* 8 + ch
- '0';
1183 } else if (ch
== 'x') {
1201 else if (ch
== 'e' && gnu_ext
)
1203 else if (ch
== '\'' || ch
== '\"' || ch
== '\\' || ch
== '?')
1206 error("invalid escaped char");
1213 /* we use 64 bit numbers */
1216 /* bn = (bn << shift) | or_val */
1217 void bn_lshift(unsigned int *bn
, int shift
, int or_val
)
1221 for(i
=0;i
<BN_SIZE
;i
++) {
1223 bn
[i
] = (v
<< shift
) | or_val
;
1224 or_val
= v
>> (32 - shift
);
1228 void bn_zero(unsigned int *bn
)
1231 for(i
=0;i
<BN_SIZE
;i
++) {
1236 void parse_number(void)
1238 int b
, t
, shift
, frac_bits
, s
, exp_val
;
1241 unsigned int bn
[BN_SIZE
];
1251 /* special dot handling */
1252 if (ch
>= '0' && ch
<= '9') {
1253 goto float_frac_parse
;
1254 } else if (ch
== '.') {
1265 } else if (t
== '0') {
1266 if (ch
== 'x' || ch
== 'X') {
1270 } else if (tcc_ext
&& (ch
== 'b' || ch
== 'B')) {
1276 /* parse all digits. cannot check octal numbers at this stage
1277 because of floating point constants */
1279 if (ch
>= 'a' & ch
<= 'f')
1281 else if (ch
>= 'A' & ch
<= 'F')
1289 if (q
>= token_buf
+ STRING_MAX_SIZE
) {
1291 error("number too long");
1297 ((ch
== 'e' || ch
== 'E') && b
== 10) ||
1298 ((ch
== 'p' || ch
== 'P') && (b
== 16 || b
== 2))) {
1300 /* NOTE: strtox should support that for hexa numbers, but
1301 non ISOC99 libcs do not support it, so we prefer to do
1303 /* hexadecimal or binary floats */
1304 /* XXX: handle overflows */
1316 } else if (t
>= 'a') {
1318 } else if (t
>= 'A') {
1323 bn_lshift(bn
, shift
, t
);
1330 if (t
>= 'a' && t
<= 'f') {
1332 } else if (t
>= 'A' && t
<= 'F') {
1334 } else if (t
>= '0' && t
<= '9') {
1340 error("invalid digit");
1341 bn_lshift(bn
, shift
, t
);
1346 if (ch
!= 'p' && ch
!= 'P')
1347 error("exponent expected");
1353 } else if (ch
== '-') {
1357 if (ch
< '0' || ch
> '9')
1358 error("exponent digits expected");
1359 while (ch
>= '0' && ch
<= '9') {
1360 exp_val
= exp_val
* 10 + ch
- '0';
1363 exp_val
= exp_val
* s
;
1365 /* now we can generate the number */
1366 /* XXX: should patch directly float number */
1367 d
= (double)bn
[1] * 4294967296.0 + (double)bn
[0];
1368 d
= ldexp(d
, exp_val
- frac_bits
);
1373 /* float : should handle overflow */
1375 } else if (t
== 'L') {
1378 /* XXX: not large enough */
1379 tokc
.ld
= (long double)d
;
1385 /* decimal floats */
1387 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1392 while (ch
>= '0' && ch
<= '9') {
1393 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1399 if (ch
== 'e' || ch
== 'E') {
1400 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1404 if (ch
== '-' || ch
== '+') {
1405 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1410 if (ch
< '0' || ch
> '9')
1411 error("exponent digits expected");
1412 while (ch
>= '0' && ch
<= '9') {
1413 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1425 tokc
.f
= strtof(token_buf
, NULL
);
1426 } else if (t
== 'L') {
1429 tokc
.ld
= strtold(token_buf
, NULL
);
1432 tokc
.d
= strtod(token_buf
, NULL
);
1436 /* integer number */
1439 if (b
== 10 && *q
== '0') {
1446 /* no need for checks except for base 10 / 8 errors */
1449 } else if (t
>= 'a') {
1451 } else if (t
>= 'A') {
1456 error("invalid digit");
1460 /* detect overflow */
1462 error("integer constant overflow");
1466 /* XXX: add unsigned constant support (ANSI) */
1467 while (ch
== 'L' || ch
== 'l' || ch
== 'U' || ch
== 'u')
1473 /* return next token without macro substitution */
1474 void next_nomacro1(void)
1482 while (ch
== '\n') {
1484 while (ch
== ' ' || ch
== 9)
1487 /* preprocessor command if # at start of line after
1492 if (ch
!= ' ' && ch
!= '\t' && ch
!= '\f')
1510 while (isid(ch
) || isnum(ch
)) {
1511 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1512 error("ident too long");
1517 ts
= tok_alloc(token_buf
, q
- token_buf
);
1519 } else if (isnum(ch
) || ch
== '.') {
1521 } else if (ch
== '\'') {
1529 } else if (ch
== '\"') {
1534 while (ch
!= '\"') {
1537 error("unterminated string");
1538 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1539 error("string too long");
1543 tokc
.ts
= tok_alloc(token_buf
, q
- token_buf
);
1546 q
= "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\247..\250##\266";
1551 if (*q
== tok
&& q
[1] == ch
) {
1554 /* three chars tests */
1555 if (tok
== TOK_SHL
| tok
== TOK_SAR
) {
1560 } else if (tok
== TOK_DOTS
) {
1562 error("parse error");
1569 /* single char substitutions */
1572 else if (tok
== '>')
1577 /* return next token without macro substitution. Can read input from
1584 tok
= tok_get(¯o_ptr
, &tokc
);
1590 /* substitute args in macro_str and return allocated string */
1591 int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
1593 int *st
, last_tok
, t
, notfirst
, *str
, len
;
1602 t
= tok_get(¯o_str
, &cval
);
1607 t
= tok_get(¯o_str
, &cval
);
1610 s
= sym_find2(args
, t
);
1612 token_buf
[0] = '\0';
1614 /* XXX: buffer overflow */
1618 strcat(token_buf
, " ");
1619 t
= tok_get(&st
, &cval
);
1620 strcat(token_buf
, get_tok_str(t
, &cval
));
1624 printf("stringize: %s\n", token_buf
);
1627 ts
= tok_alloc(token_buf
, 0);
1629 tok_add2(&str
, &len
, TOK_STR
, &cval
);
1631 tok_add2(&str
, &len
, t
, &cval
);
1633 } else if (t
>= TOK_IDENT
) {
1634 s
= sym_find2(args
, t
);
1637 /* if '##' is present before or after , no arg substitution */
1638 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
1640 tok_add(&str
, &len
, *st
++);
1642 macro_subst(&str
, &len
, nested_list
, st
);
1645 tok_add(&str
, &len
, t
);
1648 tok_add2(&str
, &len
, t
, &cval
);
1652 tok_add(&str
, &len
, 0);
1656 /* handle the '##' operator */
1657 int *macro_twosharps(int *macro_str
)
1660 int *macro_str1
, macro_str1_len
, *macro_ptr1
;
1672 while (*macro_ptr
== TOK_TWOSHARPS
) {
1674 macro_ptr1
= macro_ptr
;
1677 t
= tok_get(¯o_ptr
, &cval
);
1678 /* XXX: we handle only most common cases:
1679 ident + ident or ident + number */
1680 if (tok
>= TOK_IDENT
&&
1681 (t
>= TOK_IDENT
|| t
== TOK_NUM
)) {
1682 /* XXX: buffer overflow */
1683 p
= get_tok_str(tok
, &tokc
);
1684 strcpy(token_buf
, p
);
1685 p
= get_tok_str(t
, &cval
);
1686 strcat(token_buf
, p
);
1687 ts
= tok_alloc(token_buf
, 0);
1688 tok
= ts
->tok
; /* modify current token */
1690 /* cannot merge tokens: skip '##' */
1691 macro_ptr
= macro_ptr1
;
1696 tok_add2(¯o_str1
, ¯o_str1_len
, tok
, &tokc
);
1698 tok_add(¯o_str1
, ¯o_str1_len
, 0);
1704 /* do macro substitution of macro_str and add result to
1705 (tok_str,tok_len). If macro_str is NULL, then input stream token is
1706 substituted. 'nested_list' is the list of all macros we got inside
1707 to avoid recursing. */
1708 void macro_subst(int **tok_str
, int *tok_len
,
1709 Sym
**nested_list
, int *macro_str
)
1711 Sym
*s
, *args
, *sa
, *sa1
;
1712 int *str
, parlevel
, len
, *mstr
, t
, *saved_macro_ptr
;
1713 int mstr_allocated
, *macro_str1
;
1716 saved_macro_ptr
= macro_ptr
;
1717 macro_ptr
= macro_str
;
1720 /* first scan for '##' operator handling */
1721 macro_str1
= macro_twosharps(macro_str
);
1722 macro_ptr
= macro_str1
;
1729 /* special macros */
1730 if (tok
== TOK___LINE__
) {
1732 tok_add2(tok_str
, tok_len
, TOK_NUM
, &cval
);
1733 } else if (tok
== TOK___FILE__
) {
1734 cval
.ts
= tok_alloc(filename
, 0);
1735 tok_add2(tok_str
, tok_len
, TOK_STR
, &cval
);
1736 } else if (tok
== TOK___DATE__
) {
1737 cval
.ts
= tok_alloc("Jan 1 1970", 0);
1738 tok_add2(tok_str
, tok_len
, TOK_STR
, &cval
);
1739 } else if (tok
== TOK___TIME__
) {
1740 cval
.ts
= tok_alloc("00:00:00", 0);
1741 tok_add2(tok_str
, tok_len
, TOK_STR
, &cval
);
1742 } else if ((s
= sym_find1(&define_stack
, tok
)) != NULL
) {
1743 /* if symbol is a macro, prepare substitution */
1744 /* if nested substitution, do nothing */
1745 if (sym_find2(*nested_list
, tok
))
1749 if (s
->t
== MACRO_FUNC
) {
1750 /* NOTE: we do not use next_nomacro to avoid eating the
1751 next token. XXX: find better solution */
1755 while (ch
== ' ' || ch
== '\t' || ch
== '\n')
1759 if (t
!= '(') /* no macro subst */
1762 /* argument macro */
1767 while (tok
!= ')' && sa
) {
1771 while ((parlevel
> 0 ||
1774 sa
->v
== (TOK___VA_ARGS__
| SYM_FIELD
)))) &&
1778 else if (tok
== ')')
1780 tok_add2(&str
, &len
, tok
, &tokc
);
1783 tok_add(&str
, &len
, 0);
1784 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, 0, (int)str
);
1792 /* now subst each arg */
1793 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
1804 sym_push2(nested_list
, s
->v
, 0, 0);
1805 macro_subst(tok_str
, tok_len
, nested_list
, mstr
);
1806 /* pop nested defined symbol */
1808 *nested_list
= sa1
->prev
;
1814 /* no need to add if reading input stream */
1817 tok_add2(tok_str
, tok_len
, tok
, &tokc
);
1819 /* only replace one macro while parsing input stream */
1823 macro_ptr
= saved_macro_ptr
;
1828 /* return next token with macro substitution */
1834 /* special 'ungettok' case for label parsing */
1842 /* if not reading from macro substuted string, then try to substitute */
1846 macro_subst(&ptr
, &len
, &nested_list
, NULL
);
1848 tok_add(&ptr
, &len
, 0);
1850 macro_ptr_allocated
= ptr
;
1858 /* end of macro string: free it */
1859 free(macro_ptr_allocated
);
1866 printf("token = %s\n", get_tok_str(tok
, tokc
));
1870 void swap(int *p
, int *q
)
1878 void vsetc(int t
, int r
, CValue
*vc
)
1880 if (vtop
>= vstack
+ VSTACK_SIZE
)
1881 error("memory full");
1882 /* cannot let cpu flags if other instruction are generated */
1883 /* XXX: VT_JMP test too ? */
1884 if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
1892 /* push integer constant */
1897 vsetc(VT_INT
, VT_CONST
, &cval
);
1900 void vset(int t
, int r
, int v
)
1919 if (vtop
>= vstack
+ VSTACK_SIZE
)
1920 error("memory full");
1925 int save_reg_forced(int r
)
1930 /* store register */
1931 loc
= (loc
- 4) & -3;
1933 sv
.r
= VT_LOCAL
| VT_LVAL
;
1938 /* modify all stack values */
1939 for(p
=vstack
;p
<=vtop
;p
++) {
1940 i
= p
->r
& VT_VALMASK
;
1953 /* save r to memory. and mark it as being free */
1954 void save_reg(int r
)
1959 /* modify all stack values */
1960 for(p
=vstack
;p
<=vtop
;p
++) {
1961 i
= p
->r
& VT_VALMASK
;
1969 /* find a free register of class 'rc'. If none, save one register */
1975 /* find a free register */
1976 for(r
=0;r
<NB_REGS
;r
++) {
1977 if (reg_classes
[r
] & rc
) {
1978 for(p
=vstack
;p
<=vtop
;p
++) {
1979 i
= p
->r
& VT_VALMASK
;
1988 /* no register left : free the first one on the stack (very
1989 important to start from the bottom to ensure that we don't
1990 spill registers used in gen_op()) */
1991 for(p
=vstack
;p
<=vtop
;p
++) {
1992 r
= p
->r
& VT_VALMASK
;
1993 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
2001 void save_regs(void)
2006 for(p
=vstack
;p
<=vtop
;p
++) {
2007 r
= p
->r
& VT_VALMASK
;
2014 /* move register 's' to 'r', and flush previous value of r to memory
2016 void move_reg(int r
, int s
)
2029 /* convert a (vtop->t, vtop->c) in register. lvalues are converted as
2030 values. Cannot be used if cannot be converted to register value
2031 (such as structures). */
2034 int r
, bit_pos
, bit_size
, rc
, size
, align
, i
;
2036 /* NOTE: get_reg can modify vstack[] */
2037 if (vtop
->t
& VT_BITFIELD
) {
2038 bit_pos
= (vtop
->t
>> VT_STRUCT_SHIFT
) & 0x3f;
2039 bit_size
= (vtop
->t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
2040 /* remove bit field info to avoid loops */
2041 vtop
->t
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
2042 /* generate shifts */
2043 vpushi(32 - (bit_pos
+ bit_size
));
2045 vpushi(32 - bit_size
);
2046 /* NOTE: transformed to SHR if unsigned */
2050 if (is_float(vtop
->t
) &&
2051 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
2052 /* CPUs usually cannot use float constants, so we store them
2053 generically in data segment */
2054 size
= type_size(vtop
->t
, &align
);
2055 glo
= (glo
+ align
- 1) & -align
;
2056 /* XXX: not portable yet */
2059 ((int *)glo
)[i
] = vtop
->c
.tab
[i
];
2064 r
= vtop
->r
& VT_VALMASK
;
2065 if (r
>= VT_CONST
|| (vtop
->r
& VT_LVAL
)) {
2066 if (is_float(vtop
->t
))
2067 rc
= REG_CLASS_FLOAT
;
2078 /* handle constant optimizations and various machine independant opt */
2079 void gen_opc(int op
)
2086 /* currently, we cannot do computations with forward symbols */
2087 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
2088 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
2092 case '+': v1
->c
.i
+= fc
; break;
2093 case '-': v1
->c
.i
-= fc
; break;
2094 case '&': v1
->c
.i
&= fc
; break;
2095 case '^': v1
->c
.i
^= fc
; break;
2096 case '|': v1
->c
.i
|= fc
; break;
2097 case '*': v1
->c
.i
*= fc
; break;
2099 case '/': v1
->c
.i
/= fc
; break; /* XXX: zero case ? */
2100 case '%': v1
->c
.i
%= fc
; break; /* XXX: zero case ? */
2101 case TOK_UDIV
: v1
->c
.i
= (unsigned)v1
->c
.i
/ fc
; break; /* XXX: zero case ? */
2102 case TOK_UMOD
: v1
->c
.i
= (unsigned)v1
->c
.i
% fc
; break; /* XXX: zero case ? */
2103 case TOK_SHL
: v1
->c
.i
<<= fc
; break;
2104 case TOK_SHR
: v1
->c
.i
= (unsigned)v1
->c
.i
>> fc
; break;
2105 case TOK_SAR
: v1
->c
.i
>>= fc
; break;
2107 case TOK_ULT
: v1
->c
.i
= (unsigned)v1
->c
.i
< (unsigned)fc
; break;
2108 case TOK_UGE
: v1
->c
.i
= (unsigned)v1
->c
.i
>= (unsigned)fc
; break;
2109 case TOK_EQ
: v1
->c
.i
= v1
->c
.i
== fc
; break;
2110 case TOK_NE
: v1
->c
.i
= v1
->c
.i
!= fc
; break;
2111 case TOK_ULE
: v1
->c
.i
= (unsigned)v1
->c
.i
<= (unsigned)fc
; break;
2112 case TOK_UGT
: v1
->c
.i
= (unsigned)v1
->c
.i
> (unsigned)fc
; break;
2113 case TOK_LT
: v1
->c
.i
= v1
->c
.i
< fc
; break;
2114 case TOK_GE
: v1
->c
.i
= v1
->c
.i
>= fc
; break;
2115 case TOK_LE
: v1
->c
.i
= v1
->c
.i
<= fc
; break;
2116 case TOK_GT
: v1
->c
.i
= v1
->c
.i
> fc
; break;
2118 case TOK_LAND
: v1
->c
.i
= v1
->c
.i
&& fc
; break;
2119 case TOK_LOR
: v1
->c
.i
= v1
->c
.i
|| fc
; break;
2125 /* if commutative ops, put c2 as constant */
2126 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
2127 op
== '|' || op
== '*')) {
2132 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
2135 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
2136 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
2142 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
2143 /* try to use shifts instead of muls or divs */
2144 if (fc
> 0 && (fc
& (fc
- 1)) == 0) {
2153 else if (op
== TOK_PDIV
)
2161 /* call low level op generator */
2162 /* XXX: remove explicit registers */
2168 int pointed_size(int t
)
2170 return type_size(pointed_type(t
), &t
);
2173 /* generic gen_op: handles types problems */
2176 int u
, t1
, t2
, bt1
, bt2
, t
;
2180 bt1
= t1
& VT_BTYPE
;
2181 bt2
= t2
& VT_BTYPE
;
2183 if (is_float(bt1
) || is_float(bt2
)) {
2184 /* compute bigger type and do implicit casts */
2185 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
2187 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
2192 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
2193 op
< TOK_EQ
|| op
> TOK_GT
)
2194 error("invalid operands for binary operation");
2204 if (op
>= TOK_EQ
&& op
<= TOK_GT
) {
2205 /* the result is an int */
2210 } else if (op
== '+' || op
== '-') {
2211 if ((t1
& VT_BTYPE
) == VT_PTR
&&
2212 (t2
& VT_BTYPE
) == VT_PTR
) {
2214 error("invalid type");
2215 /* XXX: check that types are compatible */
2216 u
= pointed_size(t1
);
2218 /* set to integer type */
2222 } else if ((t1
& VT_BTYPE
) == VT_PTR
||
2223 (t2
& VT_BTYPE
) == VT_PTR
) {
2224 if ((t2
& VT_BTYPE
) == VT_PTR
) {
2228 /* stack-4 contains pointer, stack-2 value to add */
2229 vpushi(pointed_size(vtop
[-1].t
));
2232 /* put again type if gen_opc() swaped operands */
2238 /* XXX: test types and compute returned value */
2239 if ((t1
| t2
) & VT_UNSIGNED
||
2240 (t1
& VT_BTYPE
) == VT_PTR
||
2241 (t2
& VT_BTYPE
) == VT_PTR
) {
2248 else if (op
== TOK_LT
)
2250 else if (op
== TOK_GT
)
2252 else if (op
== TOK_LE
)
2254 else if (op
== TOK_GE
)
2261 /* cast 'vtop' to 't' type */
2262 void gen_cast(int t
)
2264 int bits
, sbt
, dbt
, sf
, df
, c
, st1
, dt1
;
2266 /* if not lvalue, then we convert now */
2268 sbt
= vtop
->t
& VT_BTYPE
;
2272 c
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
2274 /* convert from fp to fp */
2276 /* constant case: we can do it now */
2277 /* XXX: in ISOC, cannot do it if error in convert */
2278 if (dbt
== VT_FLOAT
&& sbt
== VT_DOUBLE
)
2279 vtop
->c
.f
= (float)vtop
->c
.d
;
2280 else if (dbt
== VT_FLOAT
&& sbt
== VT_LDOUBLE
)
2281 vtop
->c
.f
= (float)vtop
->c
.ld
;
2282 else if (dbt
== VT_DOUBLE
&& sbt
== VT_FLOAT
)
2283 vtop
->c
.d
= (double)vtop
->c
.f
;
2284 else if (dbt
== VT_DOUBLE
&& sbt
== VT_LDOUBLE
)
2285 vtop
->c
.d
= (double)vtop
->c
.ld
;
2286 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_FLOAT
)
2287 vtop
->c
.ld
= (long double)vtop
->c
.f
;
2288 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_DOUBLE
)
2289 vtop
->c
.ld
= (long double)vtop
->c
.d
;
2291 /* non constant case: generate code */
2295 /* convert int to fp */
2296 /* XXX: add const cases */
2297 st1
= vtop
->t
& (VT_BTYPE
| VT_UNSIGNED
);
2300 case VT_LLONG
| VT_UNSIGNED
:
2302 /* well, currently not needed */
2304 case VT_INT
| VT_UNSIGNED
:
2306 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.ui
; break;
2307 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.ui
; break;
2308 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.ui
; break;
2313 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.i
; break;
2314 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.i
; break;
2315 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.i
; break;
2324 /* convert fp to int */
2325 dt1
= t
& (VT_BTYPE
| VT_UNSIGNED
);
2326 /* we handle char/short/etc... with generic code */
2327 if (dt1
!= VT_INT
| VT_UNSIGNED
&&
2328 dt1
!= VT_LLONG
| VT_UNSIGNED
&&
2333 case VT_LLONG
| VT_UNSIGNED
:
2335 /* well, currently not needed */
2337 case VT_INT
| VT_UNSIGNED
:
2339 case VT_FLOAT
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
2340 case VT_DOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
2341 case VT_LDOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
2347 case VT_FLOAT
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
2348 case VT_DOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
2349 case VT_LDOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
2357 if (dt1
== VT_INT
&& (t
& (VT_TYPE
| VT_UNSIGNED
)) != dt1
) {
2358 /* additionnal cast for char/short/bool... */
2359 vtop
->t
= (vtop
->t
& ~VT_TYPE
) | dt1
;
2362 } else if (dbt
== VT_BOOL
) {
2365 } else if ((dbt
== VT_BYTE
|| dbt
== VT_SHORT
) &&
2366 !(vtop
->r
& VT_LVAL
)) {
2367 /* no need to apply if lvalue because we do it while
2368 loading the value */
2373 if (t
& VT_UNSIGNED
) {
2374 vpushi((1 << bits
) - 1);
2388 /* return type size. Put alignment at 'a' */
2389 int type_size(int t
, int *a
)
2395 if (bt
== VT_STRUCT
) {
2397 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
2398 *a
= 4; /* XXX: cannot store it yet. Doing that is safe */
2400 } else if (bt
== VT_PTR
) {
2402 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
2403 return type_size(s
->t
, a
) * s
->c
;
2408 } else if (bt
== VT_LDOUBLE
) {
2410 return LDOUBLE_SIZE
;
2411 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
2414 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
2417 } else if (bt
== VT_SHORT
) {
2421 /* char, void, function, _Bool */
2427 /* return the pointed type of t */
2428 int pointed_type(int t
)
2431 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
2432 return s
->t
| (t
& ~VT_TYPE
);
2435 int mk_pointer(int t
)
2440 return VT_PTR
| (p
<< VT_STRUCT_SHIFT
) | (t
& ~VT_TYPE
);
2443 int is_compatible_types(int t1
, int t2
)
2450 bt1
= t1
& VT_BTYPE
;
2451 bt2
= t2
& VT_BTYPE
;
2452 if (bt1
== VT_PTR
) {
2453 t1
= pointed_type(t1
);
2454 /* if function, then convert implicitely to function pointer */
2455 if (bt2
!= VT_FUNC
) {
2458 t2
= pointed_type(t2
);
2460 /* void matches everything */
2463 if (t1
== VT_VOID
|| t2
== VT_VOID
)
2465 return is_compatible_types(t1
, t2
);
2466 } else if (bt1
== VT_STRUCT
) {
2468 } else if (bt1
== VT_FUNC
) {
2471 s1
= sym_find(((unsigned)t1
>> VT_STRUCT_SHIFT
));
2472 s2
= sym_find(((unsigned)t2
>> VT_STRUCT_SHIFT
));
2473 if (!is_compatible_types(s1
->t
, s2
->t
))
2475 /* XXX: not complete */
2476 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
2480 while (s1
!= NULL
) {
2483 if (!is_compatible_types(s1
->t
, s2
->t
))
2492 /* XXX: not complete */
2497 int check_assign_types(int t1
, int t2
)
2501 if ((t1
& VT_BTYPE
) == VT_PTR
&&
2502 (t2
& VT_BTYPE
) == VT_FUNC
) {
2503 return is_compatible_types(pointed_type(t1
), t2
);
2505 return is_compatible_types(t1
, t2
);
2509 /* print a type. If 'varstr' is not NULL, then the variable is also
2510 printed in the type */
2511 /* XXX: add array and function pointers */
2512 /* XXX: buffer overflows */
2513 void type_to_str(char *buf
, int buf_size
,
2514 int t
, const char *varstr
)
2523 if (t
& VT_UNSIGNED
)
2524 strcat(buf
, "unsigned ");
2527 strcat(buf
, "void");
2530 strcat(buf
, "_Bool");
2533 strcat(buf
, "char");
2536 strcat(buf
, "short");
2542 strcat(buf
, "long");
2545 strcat(buf
, "long long");
2548 strcat(buf
, "float");
2551 strcat(buf
, "double");
2554 strcat(buf
, "long double");
2558 if (bt
== VT_STRUCT
)
2559 strcat(buf
, "struct ");
2561 strcat(buf
, "enum ");
2562 v
= (unsigned)t
>> VT_STRUCT_SHIFT
;
2563 if (v
>= SYM_FIRST_ANOM
)
2564 strcat(buf
, "<anonymous>");
2566 strcat(buf
, get_tok_str(v
, NULL
));
2569 s
= sym_find((unsigned)t
>> VT_STRUCT_SHIFT
);
2570 type_to_str(buf
, buf_size
, s
->t
, varstr
);
2573 while (sa
!= NULL
) {
2574 type_to_str(buf1
, sizeof(buf1
), sa
->t
, NULL
);
2583 s
= sym_find((unsigned)t
>> VT_STRUCT_SHIFT
);
2586 strcat(buf1
, varstr
);
2587 type_to_str(buf
, buf_size
, s
->t
, buf1
);
2592 strcat(buf
, varstr
);
2599 /* verify type compatibility to store vtop in 'st' type, and generate
2601 void gen_assign_cast(int dt
)
2604 char buf1
[256], buf2
[256];
2606 st
= vtop
->t
; /* destination type */
2607 if (!check_assign_types(dt
, st
)) {
2608 type_to_str(buf1
, sizeof(buf1
), st
, NULL
);
2609 type_to_str(buf2
, sizeof(buf2
), dt
, NULL
);
2610 error("cannot cast '%s' to '%s'", buf1
, buf2
);
2612 if ((dt
& VT_BTYPE
) == VT_BOOL
|| is_float(dt
)) {
2613 gen_cast(dt
& VT_BTYPE
);
2618 /* store vtop in lvalue pushed on stack */
2621 int ft
, r
, t
, size
, align
, bit_size
, bit_pos
;
2625 gen_assign_cast(ft
& VT_TYPE
);
2627 if ((vtop
->t
& VT_BTYPE
) == VT_STRUCT
) {
2628 /* if structure, only generate pointer */
2629 /* structure assignment : generate memcpy */
2630 /* XXX: optimize if small size */
2635 size
= type_size(vtop
->t
, &align
);
2640 vtop
->r
&= ~VT_LVAL
;
2645 vtop
->r
&= ~VT_LVAL
;
2649 vpushi((int)&memcpy
);
2651 /* leave source on stack */
2652 } else if (ft
& VT_BITFIELD
) {
2653 /* bitfield store handling */
2654 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
2655 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
2656 /* remove bit field info to avoid loops */
2657 vtop
[-1].t
= ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
2659 /* duplicate destination */
2661 vtop
[-1] = vtop
[-2];
2663 /* mask and shift source */
2664 vpushi((1 << bit_size
) - 1);
2668 /* load destination, mask and or with source */
2670 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
2676 r
= gv(); /* generate value */
2677 /* if lvalue was saved on stack, must read it */
2678 if ((vtop
[-1].r
& VT_VALMASK
) == VT_LLOCAL
) {
2680 t
= get_reg(REG_CLASS_INT
);
2682 sv
.r
= VT_LOCAL
| VT_LVAL
;
2683 sv
.c
.ul
= vtop
[-1].c
.ul
;
2685 vtop
[-1].r
= t
| VT_LVAL
;
2694 /* post defines POST/PRE add. c is the token ++ or -- */
2695 void inc(int post
, int c
)
2702 vdup(); /* room for returned value */
2703 vdup(); /* save lvalue */
2706 /* duplicate value */
2707 /* XXX: handle floats */
2708 r1
= get_reg(REG_CLASS_INT
);
2712 load(r1
, &sv
); /* move r to r1 */
2713 /* duplicates value */
2718 vpushi(c
- TOK_MID
);
2720 vstore(); /* store value */
2722 vpop(); /* if post op, return saved value */
2725 /* enum/struct/union declaration */
2726 int struct_decl(int u
)
2728 int a
, t
, b
, v
, size
, align
, maxalign
, c
, offset
;
2729 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
;
2732 a
= tok
; /* save decl type */
2737 /* struct already defined ? return it */
2738 /* XXX: check consistency */
2739 if (s
= sym_find(v
| SYM_STRUCT
)) {
2741 error("invalid type");
2747 s
= sym_push(v
| SYM_STRUCT
, a
, 0);
2748 /* put struct/union/enum name in type */
2750 u
= u
| (v
<< VT_STRUCT_SHIFT
);
2755 error("struct/union/enum already defined");
2756 /* cannot be empty */
2763 if (a
== TOK_ENUM
) {
2770 /* enum symbols have static storage */
2771 sym_push(v
, VT_CONST
| VT_STATIC
, c
);
2781 t
= type_decl(&v
, b
, TYPE_DIRECT
);
2782 if ((t
& VT_BTYPE
) == VT_FUNC
||
2783 (t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
)))
2784 error("invalid type for '%s'",
2785 get_tok_str(v
, NULL
));
2791 bit_size
= expr_const();
2792 /* XXX: handle v = 0 case for messages */
2794 error("negative width in bit-field '%s'",
2795 get_tok_str(v
, NULL
));
2796 if (v
&& bit_size
== 0)
2797 error("zero width for bit-field '%s'",
2798 get_tok_str(v
, NULL
));
2800 size
= type_size(t
, &align
);
2802 if (bit_size
>= 0) {
2807 error("bitfields must have scalar type");
2809 if (bit_size
> bsize
) {
2810 error("width of '%s' exceeds its type",
2811 get_tok_str(v
, NULL
));
2812 } else if (bit_size
== bsize
) {
2813 /* no need for bit fields */
2815 } else if (bit_size
== 0) {
2816 /* XXX: what to do if only padding in a
2818 /* zero size: means to pad */
2822 /* we do not have enough room ? */
2823 if ((bit_pos
+ bit_size
) > bsize
)
2826 /* XXX: handle LSB first */
2828 (bit_pos
<< VT_STRUCT_SHIFT
) |
2829 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
2830 bit_pos
+= bit_size
;
2836 /* add new memory data only if starting
2838 if (lbit_pos
== 0) {
2839 if (a
== TOK_STRUCT
) {
2840 c
= (c
+ align
- 1) & -align
;
2848 if (align
> maxalign
)
2852 printf("add field %s offset=%d",
2853 get_tok_str(v
, NULL
), offset
);
2854 if (t
& VT_BITFIELD
) {
2855 printf(" pos=%d size=%d",
2856 (t
>> VT_STRUCT_SHIFT
) & 0x3f,
2857 (t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
2861 ss
= sym_push(v
| SYM_FIELD
, t
, offset
);
2865 if (tok
== ';' || tok
== -1)
2875 /* size for struct/union, dummy for enum */
2876 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
2881 /* return 0 if no type declaration. otherwise, return the basic type
2883 XXX: A '2' is ored to ensure non zero return if int type.
2899 if ((t
& VT_BTYPE
) != 0)
2900 error("too many basic types");
2914 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
2915 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
2916 } else if ((t
& VT_BTYPE
) == VT_LONG
) {
2917 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
2931 if ((t
& VT_BTYPE
) == VT_LONG
) {
2932 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
2939 u
= struct_decl(VT_ENUM
);
2943 u
= struct_decl(VT_STRUCT
);
2946 /* type modifiers */
2976 if (!s
|| !(s
->t
& VT_TYPEDEF
))
2978 t
|= (s
->t
& ~VT_TYPEDEF
);
2985 /* long is never used as type */
2986 if ((t
& VT_BTYPE
) == VT_LONG
)
2987 t
= (t
& ~VT_BTYPE
) | VT_INT
;
2991 int post_type(int t
)
2993 int p
, n
, pt
, l
, t1
;
2994 Sym
**plast
, *s
, *first
;
2997 /* function declaration */
3002 while (tok
!= ')') {
3003 /* read param name and compute offset */
3004 if (l
!= FUNC_OLD
) {
3005 if (!(pt
= ist())) {
3007 error("invalid type");
3014 if ((pt
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
3016 pt
= type_decl(&n
, pt
, TYPE_DIRECT
| TYPE_ABSTRACT
);
3017 if ((pt
& VT_BTYPE
) == VT_VOID
)
3018 error("parameter declared as void");
3025 /* array must be transformed to pointer according to ANSI C */
3027 s
= sym_push(n
| SYM_FIELD
, pt
, 0);
3032 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
3039 /* if no parameters, then old type prototype */
3043 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
3044 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
));
3045 /* we push a anonymous symbol which will contain the function prototype */
3047 s
= sym_push(p
, t
, l
);
3049 t
= t1
| VT_FUNC
| (p
<< VT_STRUCT_SHIFT
);
3050 } else if (tok
== '[') {
3051 /* array definition */
3057 error("invalid array size");
3060 /* parse next post type */
3061 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
3062 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
));
3064 /* we push a anonymous symbol which will contain the array
3068 t
= t1
| VT_ARRAY
| VT_PTR
| (p
<< VT_STRUCT_SHIFT
);
3073 /* Read a type declaration (except basic type), and return the
3074 type. If v is true, then also put variable name in 'vtop->c' */
3075 int type_decl(int *v
, int t
, int td
)
3080 t
= t
& -3; /* suppress the ored '2' */
3081 while (tok
== '*') {
3083 while (tok
== TOK_CONST
|| tok
== TOK_VOLATILE
|| tok
== TOK_RESTRICT
)
3088 /* recursive type */
3089 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
3092 u
= type_decl(v
, 0, td
);
3096 /* type identifier */
3097 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
3101 if (!(td
& TYPE_ABSTRACT
))
3102 expect("identifier");
3106 /* append t at the end of u */
3112 s
= sym_find((unsigned)p
>> VT_STRUCT_SHIFT
);
3122 /* define a new external reference to a function 'v' of type 'u' */
3123 Sym
*external_sym(int v
, int u
)
3128 /* push forward reference */
3129 s
= sym_push1(&global_stack
,
3130 v
, u
| VT_CONST
| VT_FORWARD
, 0);
3137 if (vtop
->r
& VT_LVAL
)
3139 if ((vtop
->t
& VT_BTYPE
) != VT_PTR
)
3141 vtop
->t
= pointed_type(vtop
->t
);
3142 if (!(vtop
->t
& VT_ARRAY
)) /* an array is never an lvalue */
3146 /* pass a parameter to a function and do type checking and casting */
3147 void gfunc_param_typed(GFuncContext
*gf
, Sym
*func
, Sym
*arg
)
3150 func_type
= func
->c
;
3151 if (func_type
== FUNC_OLD
||
3152 (func_type
== FUNC_ELLIPSIS
&& arg
== NULL
)) {
3153 /* default casting : only need to convert float to double */
3154 if ((vtop
->t
& VT_BTYPE
) == VT_FLOAT
)
3155 gen_cast(VT_DOUBLE
);
3156 } else if (arg
== NULL
) {
3157 error("too many arguments to function");
3159 gen_assign_cast(arg
->t
);
3166 int n
, t
, ft
, fc
, p
, align
, size
;
3170 if (tok
== TOK_NUM
|| tok
== TOK_CCHAR
|| tok
== TOK_LCHAR
) {
3173 } else if (tok
== TOK_CFLOAT
) {
3174 vsetc(VT_FLOAT
, VT_CONST
, &tokc
);
3176 } else if (tok
== TOK_CDOUBLE
) {
3177 vsetc(VT_DOUBLE
, VT_CONST
, &tokc
);
3179 } else if (tok
== TOK_CLDOUBLE
) {
3180 vsetc(VT_LDOUBLE
, VT_CONST
, &tokc
);
3182 } else if (tok
== TOK___FUNC__
) {
3183 /* special function name identifier */
3184 /* generate (char *) type */
3185 vset(mk_pointer(VT_BYTE
), VT_CONST
, glo
);
3186 strcpy((void *)glo
, funcname
);
3187 glo
+= strlen(funcname
) + 1;
3189 } else if (tok
== TOK_LSTR
) {
3192 } else if (tok
== TOK_STR
) {
3193 /* string parsing */
3196 type_size(t
, &align
);
3197 glo
= (glo
+ align
- 1) & -align
;
3199 /* we must declare it as an array first to use initializer parser */
3200 t
= VT_CONST
| VT_ARRAY
| mk_pointer(t
);
3201 decl_initializer(t
, glo
, 1, 0);
3202 glo
+= type_size(t
, &align
);
3203 /* put it as pointer */
3204 vset(t
& ~VT_ARRAY
, VT_CONST
, fc
);
3211 ft
= type_decl(&n
, t
, TYPE_ABSTRACT
);
3213 /* check ISOC99 compound literal */
3215 /* data is allocated locally by default */
3220 /* all except arrays are lvalues */
3221 if (!(ft
& VT_ARRAY
))
3223 fc
= decl_initializer_alloc(ft
, 1);
3224 vset(ft
& VT_TYPE
, ft
& (VT_VALMASK
| VT_LVAL
), fc
);
3233 } else if (t
== '*') {
3236 } else if (t
== '&') {
3238 /* functions names must be treated as function pointers,
3239 except for unary '&' and sizeof. Since we consider that
3240 functions are not lvalues, we only have to handle it
3241 there and in function calls. */
3242 if ((vtop
->t
& VT_BTYPE
) != VT_FUNC
)
3244 vtop
->t
= mk_pointer(vtop
->t
);
3245 vtop
->r
&= ~VT_LVAL
;
3249 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
)
3250 vtop
->c
.i
= !vtop
->c
.i
;
3251 else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
3252 vtop
->c
.i
= vtop
->c
.i
^ 1;
3254 vset(VT_INT
, VT_JMP
, gtst(1, 0));
3264 if (t
== TOK_SIZEOF
) {
3268 t
= type_decl(&n
, t
, TYPE_ABSTRACT
);
3270 /* XXX: some code could be generated: add eval
3282 vpushi(type_size(t
, &t
));
3284 if (t
== TOK_INC
|| t
== TOK_DEC
) {
3287 } else if (t
== '-') {
3296 error("'%s' undeclared", get_tok_str(t
, NULL
));
3297 /* for simple function calls, we tolerate undeclared
3298 external reference */
3300 sym_push1(&global_stack
, p
, 0, FUNC_OLD
);
3301 /* int() function */
3302 s
= external_sym(t
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
));
3304 vset(s
->t
& VT_TYPE
,
3305 s
->t
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
), s
->c
);
3306 /* if forward reference, we must point to s */
3307 if (vtop
->r
& VT_FORWARD
)
3312 /* post operations */
3314 if (tok
== TOK_INC
| tok
== TOK_DEC
) {
3317 } else if (tok
== '.' | tok
== TOK_ARROW
) {
3319 if (tok
== TOK_ARROW
)
3322 vtop
->r
&= ~VT_LVAL
;
3324 /* expect pointer on structure */
3325 if ((vtop
->t
& VT_BTYPE
) != VT_STRUCT
)
3326 expect("struct or union");
3327 s
= sym_find(((unsigned)vtop
->t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
3330 while (s
= s
->next
) {
3335 error("field not found");
3336 /* add field offset to pointer */
3337 vtop
->t
= VT_INT
; /* change type to int */
3340 /* change type to field type, and set to lvalue */
3342 /* an array is never an lvalue */
3343 if (!(vtop
->t
& VT_ARRAY
))
3346 } else if (tok
== '[') {
3352 } else if (tok
== '(') {
3357 if ((vtop
->t
& VT_BTYPE
) != VT_FUNC
) {
3358 /* pointer test (no array accepted) */
3359 if ((vtop
->t
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
3360 vtop
->t
= pointed_type(vtop
->t
);
3361 if ((vtop
->t
& VT_BTYPE
) != VT_FUNC
)
3365 expect("function pointer");
3368 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
3370 /* get return type */
3371 s
= sym_find((unsigned)vtop
->t
>> VT_STRUCT_SHIFT
);
3372 save_regs(); /* save used temporary registers */
3375 sa
= s
->next
; /* first parameter */
3376 #ifdef INVERT_FUNC_PARAMS
3378 int *str
, len
, parlevel
, *saved_macro_ptr
;
3381 /* read each argument and store it on a stack */
3382 /* XXX: merge it with macro args ? */
3384 while (tok
!= ')') {
3388 while ((parlevel
> 0 || (tok
!= ')' && tok
!= ',')) &&
3392 else if (tok
== ')')
3394 tok_add2(&str
, &len
, tok
, &tokc
);
3397 tok_add(&str
, &len
, -1); /* end of file added */
3398 tok_add(&str
, &len
, 0);
3399 s1
= sym_push2(&args
, 0, 0, (int)str
);
3400 s1
->next
= sa
; /* add reference to argument */
3410 /* now generate code in reverse order by reading the stack */
3411 saved_macro_ptr
= macro_ptr
;
3413 macro_ptr
= (int *)args
->c
;
3417 expect("',' or ')'");
3418 gfunc_param_typed(&gf
, s
, args
->next
);
3420 free((int *)args
->c
);
3424 macro_ptr
= saved_macro_ptr
;
3429 /* compute first implicit argument if a structure is returned */
3430 if ((s
->t
& VT_BTYPE
) == VT_STRUCT
) {
3431 /* get some space for the returned structure */
3432 size
= type_size(s
->t
, &align
);
3433 loc
= (loc
- size
) & -align
;
3435 ret
.r
= VT_LOCAL
| VT_LVAL
;
3436 /* pass it as 'int' to avoid structure arg passing
3438 vset(VT_INT
, VT_LOCAL
, loc
);
3443 ret
.r
= FUNC_RET_REG
; /* return in register */
3446 #ifndef INVERT_FUNC_PARAMS
3447 while (tok
!= ')') {
3449 gfunc_param_typed(&gf
, s
, sa
);
3457 error("too few arguments to function");
3461 vsetc(ret
.t
, ret
.r
, &ret
.c
);
3474 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
3475 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
3476 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
3499 while ((l
== 0 & (tok
== '*' | tok
== '/' | tok
== '%')) |
3500 (l
== 1 & (tok
== '+' | tok
== '-')) |
3501 (l
== 2 & (tok
== TOK_SHL
| tok
== TOK_SAR
)) |
3502 (l
== 3 & ((tok
>= TOK_ULE
& tok
<= TOK_GT
) |
3503 tok
== TOK_ULT
| tok
== TOK_UGE
)) |
3504 (l
== 4 & (tok
== TOK_EQ
| tok
== TOK_NE
)) |
3505 (l
== 5 & tok
== '&') |
3506 (l
== 6 & tok
== '^') |
3507 (l
== 7 & tok
== '|') |
3508 (l
== 8 & tok
== TOK_LAND
) |
3509 (l
== 9 & tok
== TOK_LOR
)) {
3518 /* only used if non constant */
3526 if (tok
!= TOK_LAND
) {
3529 vset(VT_INT
, VT_JMPI
, t
);
3546 if (tok
!= TOK_LOR
) {
3549 vset(VT_INT
, VT_JMP
, t
);
3559 /* XXX: better constant handling */
3562 int t
, u
, c
, r1
, r2
;
3611 /* parse a constant expression and return value in vtop */
3612 void expr_const1(void)
3618 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) != VT_CONST
)
3623 /* parse an integer constant and return its value */
3624 int expr_const(void)
3633 /* return the label token if current token is a label, otherwise
3640 /* fast test first */
3641 if (tok
< TOK_UIDENT
)
3643 /* no need to save tokc since we expect an identifier */
3651 /* XXX: may not work in all cases (macros ?) */
3660 void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
, int case_reg
)
3665 if (tok
== TOK_IF
) {
3672 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3674 if (c
== TOK_ELSE
) {
3678 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3679 gsym(d
); /* patch else jmp */
3682 } else if (tok
== TOK_WHILE
) {
3690 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
3691 oad(0xe9, d
- ind
- 5); /* jmp */
3694 } else if (tok
== '{') {
3697 s
= local_stack
.top
;
3698 while (tok
!= '}') {
3701 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3703 /* pop locally defined symbols */
3704 sym_pop(&local_stack
, s
);
3706 } else if (tok
== TOK_RETURN
) {
3710 if ((func_vt
& VT_BTYPE
) == VT_STRUCT
) {
3711 /* if returning structure, must copy it to implicit
3712 first pointer arg location */
3713 vset(mk_pointer(func_vt
), VT_LOCAL
| VT_LVAL
, func_vc
);
3716 /* copy structure value to pointer */
3718 } else if (is_float(func_vt
)) {
3719 /* move return value to float return register */
3720 move_reg(FUNC_RET_FREG
, gv());
3722 /* move return value to standard return register */
3723 move_reg(FUNC_RET_REG
, gv());
3728 rsym
= gjmp(rsym
); /* jmp */
3729 } else if (tok
== TOK_BREAK
) {
3732 error("cannot break");
3733 *bsym
= gjmp(*bsym
);
3736 } else if (tok
== TOK_CONTINUE
) {
3739 error("cannot continue");
3740 *csym
= gjmp(*csym
);
3743 } else if (tok
== TOK_FOR
) {
3766 oad(0xe9, d
- ind
- 5); /* jmp */
3770 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
3771 oad(0xe9, c
- ind
- 5); /* jmp */
3775 if (tok
== TOK_DO
) {
3780 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
3791 if (tok
== TOK_SWITCH
) {
3799 b
= gjmp(0); /* jump to first case */
3801 block(&a
, csym
, &b
, &c
, case_reg
);
3802 /* if no default, jmp after switch */
3810 if (tok
== TOK_CASE
) {
3815 /* since a case is like a label, we must skip it with a jmp */
3818 vset(VT_INT
, case_reg
, 0);
3821 *case_sym
= gtst(1, 0);
3824 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3826 if (tok
== TOK_DEFAULT
) {
3832 error("too many 'default'");
3834 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3836 if (tok
== TOK_GOTO
) {
3838 s
= sym_find1(&label_stack
, tok
);
3839 /* put forward definition if needed */
3841 s
= sym_push1(&label_stack
, tok
, VT_FORWARD
, 0);
3842 /* label already defined */
3843 if (s
->t
& VT_FORWARD
)
3844 s
->c
= gjmp(s
->c
); /* jmp xxx */
3846 oad(0xe9, s
->c
- ind
- 5); /* jmp xxx */
3853 s
= sym_find1(&label_stack
, b
);
3855 if (!(s
->t
& VT_FORWARD
))
3856 error("multiple defined label");
3861 sym_push1(&label_stack
, b
, 0, ind
);
3863 /* we accept this, but it is a mistake */
3865 warning("deprecated use of label at end of compound statement");
3867 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3869 /* expression case */
3879 /* t is the array or struct type. c is the array or struct
3880 address. cur_index/cur_field is the pointer to the current
3881 value. 'size_only' is true if only size info is needed (only used
3883 void decl_designator(int t
, int c
,
3884 int *cur_index
, Sym
**cur_field
,
3888 int notfirst
, index
, align
, l
;
3891 if (gnu_ext
&& (l
= is_label()) != 0)
3894 while (tok
== '[' || tok
== '.') {
3896 if (!(t
& VT_ARRAY
))
3897 expect("array type");
3898 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3900 index
= expr_const();
3901 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
3902 expect("invalid index");
3906 t
= pointed_type(t
);
3907 c
+= index
* type_size(t
, &align
);
3913 if ((t
& VT_BTYPE
) != VT_STRUCT
)
3914 expect("struct/union type");
3915 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
3927 t
= f
->t
| (t
& ~VT_TYPE
);
3942 t
= pointed_type(t
);
3943 c
+= index
* type_size(t
, &align
);
3947 error("too many field init");
3948 t
= f
->t
| (t
& ~VT_TYPE
);
3952 decl_initializer(t
, c
, 0, size_only
);
3955 /* store a value or an expression directly in global data or in local array */
3957 void init_putv(int t
, int c
, int v
, int is_expr
)
3959 int saved_global_expr
, bt
;
3961 if ((t
& VT_VALMASK
) == VT_CONST
) {
3963 /* compound literals must be allocated globally in this case */
3964 saved_global_expr
= global_expr
;
3967 global_expr
= saved_global_expr
;
3971 /* XXX: do casting */
3972 /* XXX: not portable */
3973 bt
= vtop
->t
& VT_BTYPE
;
3976 *(char *)c
= vtop
->c
.i
;
3979 *(short *)c
= vtop
->c
.i
;
3982 *(double *)c
= vtop
->c
.d
;
3985 *(long double *)c
= vtop
->c
.ld
;
3989 *(long long *)c
= vtop
->c
.ll
;
3993 *(int *)c
= vtop
->c
.i
;
3998 vset(t
& VT_TYPE
, t
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
), c
);
4008 /* put zeros for variable based init */
4009 void init_putz(int t
, int c
, int size
)
4013 if ((t
& VT_VALMASK
) == VT_CONST
) {
4014 /* nothing to do because global are already set to zero */
4021 vset(VT_INT
, VT_LOCAL
, c
);
4023 vpushi((int)&memset
);
4028 /* 't' contains the type and storage info. c is the address of the
4029 object. 'first' is true if array '{' must be read (multi dimension
4030 implicit array init handling). 'size_only' is true if size only
4031 evaluation is wanted (only for arrays). */
4032 void decl_initializer(int t
, int c
, int first
, int size_only
)
4034 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
4035 int t1
, size1
, align1
;
4040 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
4043 t1
= pointed_type(t
);
4044 size1
= type_size(t1
, &align1
);
4047 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
4053 /* only parse strings here if correct type (otherwise: handle
4054 them as ((w)char *) expressions */
4055 if ((tok
== TOK_LSTR
&&
4056 (t1
& VT_BTYPE
) == VT_INT
) ||
4058 (t1
& VT_BTYPE
) == VT_BYTE
)) {
4059 /* XXX: move multiple string parsing in parser ? */
4060 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
4062 /* compute maximum number of chars wanted */
4064 if (n
>= 0 && nb
> (n
- array_length
))
4065 nb
= n
- array_length
;
4068 warning("initializer-string for array is too long");
4070 init_putv(t1
, c
+ (array_length
+ i
) * size1
,
4077 /* only add trailing zero if enough storage (no
4078 warning in this case since it is standard) */
4079 if (n
< 0 || array_length
< n
) {
4081 init_putv(t1
, c
+ (array_length
* size1
), 0, 0);
4087 while (tok
!= '}') {
4088 decl_designator(t
, c
, &index
, NULL
, size_only
);
4089 if (n
>= 0 && index
>= n
)
4090 error("index too large");
4091 /* must put zero in holes (note that doing it that way
4092 ensures that it even works with designators) */
4093 if (!size_only
&& array_length
< index
) {
4094 init_putz(t1
, c
+ array_length
* size1
,
4095 (index
- array_length
) * size1
);
4098 if (index
> array_length
)
4099 array_length
= index
;
4100 /* special test for multi dimensional arrays (may not
4101 be strictly correct if designators are used at the
4103 if (index
>= n
&& no_oblock
)
4112 /* put zeros at the end */
4113 if (!size_only
&& n
>= 0 && array_length
< n
) {
4114 init_putz(t1
, c
+ array_length
* size1
,
4115 (n
- array_length
) * size1
);
4117 /* patch type size if needed */
4119 s
->c
= array_length
;
4120 } else if ((t
& VT_BTYPE
) == VT_STRUCT
&& tok
== '{') {
4121 /* XXX: union needs only one init */
4123 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
4128 while (tok
!= '}') {
4129 decl_designator(t
, c
, NULL
, &f
, size_only
);
4130 /* fill with zero between fields */
4132 if (!size_only
&& array_length
< index
) {
4133 init_putz(t
, c
+ array_length
,
4134 index
- array_length
);
4136 index
= index
+ type_size(f
->t
, &align1
);
4137 if (index
> array_length
)
4138 array_length
= index
;
4144 /* put zeros at the end */
4145 if (!size_only
&& array_length
< n
) {
4146 init_putz(t
, c
+ array_length
,
4150 } else if (tok
== '{') {
4152 decl_initializer(t
, c
, first
, size_only
);
4154 } else if (size_only
) {
4155 /* just skip expression */
4157 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
4161 else if (tok
== ')')
4166 init_putv(t
, c
, 0, 1);
4170 /* parse an initializer for type 't' if 'has_init' is true, and
4171 allocate space in local or global data space. The allocated address
4173 int decl_initializer_alloc(int t
, int has_init
)
4175 int size
, align
, addr
, tok1
;
4176 int *init_str
, init_len
, level
, *saved_macro_ptr
;
4178 size
= type_size(t
, &align
);
4179 /* If unknown size, we must evaluate it before
4180 evaluating initializers because
4181 initializers can generate global data too
4182 (e.g. string pointers or ISOC99 compound
4183 literals). It also simplifies local
4184 initializers handling */
4187 saved_macro_ptr
= NULL
; /* avoid warning */
4191 error("unknown type size");
4192 /* get all init string */
4194 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
4196 error("unexpected end of file in initializer");
4197 tok_add2(&init_str
, &init_len
, tok
, &tokc
);
4200 else if (tok
== '}') {
4208 tok_add(&init_str
, &init_len
, -1);
4209 tok_add(&init_str
, &init_len
, 0);
4212 saved_macro_ptr
= macro_ptr
;
4213 macro_ptr
= init_str
;
4215 decl_initializer(t
, 0, 1, 1);
4216 /* prepare second initializer parsing */
4217 macro_ptr
= init_str
;
4220 /* if still unknown size, error */
4221 size
= type_size(t
, &align
);
4223 error("unknown type size");
4225 if ((t
& VT_VALMASK
) == VT_LOCAL
) {
4226 loc
= (loc
- size
) & -align
;
4229 glo
= (glo
+ align
- 1) & -align
;
4231 /* very important to increment global
4232 pointer at this time because
4233 initializers themselves can create new
4238 decl_initializer(t
, addr
, 1, 0);
4239 /* restore parse state if needed */
4242 macro_ptr
= saved_macro_ptr
;
4250 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
4253 int *a
, t
, b
, v
, u
, addr
, has_init
, size
, align
;
4259 /* skip redundant ';' */
4260 /* XXX: find more elegant solution */
4265 /* special test for old K&R protos without explicit int
4266 type. Only accepted when defining global data */
4267 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
4271 if (((b
& VT_BTYPE
) == VT_ENUM
||
4272 (b
& VT_BTYPE
) == VT_STRUCT
) &&
4274 /* we accept no variable after */
4278 while (1) { /* iterate thru each declaration */
4279 t
= type_decl(&v
, b
, TYPE_DIRECT
);
4283 type_to_str(buf
, sizeof(buf
), t
, get_tok_str(v
, NULL
));
4284 printf("type = '%s'\n", buf
);
4289 error("cannot use local functions");
4291 expect("function definition");
4292 /* patch forward references */
4293 if ((sym
= sym_find(v
)) && (sym
->t
& VT_FORWARD
)) {
4294 greloc_patch(sym
, ind
);
4295 sym
->t
= VT_CONST
| t
;
4297 /* put function address */
4298 sym_push1(&global_stack
, v
, VT_CONST
| t
, ind
);
4300 funcname
= get_tok_str(v
, NULL
);
4301 /* push a dummy symbol to enable local sym storage */
4302 sym_push1(&local_stack
, 0, 0, 0);
4303 /* define parameters */
4304 sym
= sym_find((unsigned)t
>> VT_STRUCT_SHIFT
);
4305 /* XXX: the following is x86 dependant -> move it to
4308 /* if the function returns a structure, then add an
4309 implicit pointer parameter */
4311 if ((func_vt
& VT_BTYPE
) == VT_STRUCT
) {
4315 while (sym
= sym
->next
) {
4317 sym_push(sym
->v
& ~SYM_FIELD
,
4318 u
| VT_LOCAL
| VT_LVAL
,
4320 size
= type_size(u
, &align
);
4321 size
= (size
+ 3) & ~3;
4322 #ifdef FUNC_STRUCT_PARAM_AS_PTR
4323 /* structs are passed as pointer */
4324 if ((u
& VT_BTYPE
) == VT_STRUCT
) {
4331 o(0xe58955); /* push %ebp, mov %esp, %ebp */
4332 a
= (int *)oad(0xec81, 0); /* sub $xxx, %esp */
4334 block(NULL
, NULL
, NULL
, NULL
, 0);
4336 o(0xc3c9); /* leave, ret */
4337 *a
= (-loc
+ 3) & -4; /* align local size to word &
4338 save local variables */
4339 sym_pop(&label_stack
, NULL
); /* reset label stack */
4340 sym_pop(&local_stack
, NULL
); /* reset local stack */
4341 funcname
= ""; /* for safety */
4342 func_vt
= VT_VOID
; /* for safety */
4345 if (b
& VT_TYPEDEF
) {
4346 /* save typedefed type */
4347 /* XXX: test storage specifiers ? */
4348 sym_push(v
, t
| VT_TYPEDEF
, 0);
4349 } else if ((t
& VT_BTYPE
) == VT_FUNC
) {
4350 /* external function definition */
4353 /* not lvalue if array */
4354 if (!(t
& VT_ARRAY
))
4356 if (b
& VT_EXTERN
) {
4357 /* external variable */
4364 has_init
= (tok
== '=');
4367 addr
= decl_initializer_alloc(u
, has_init
);
4368 if (l
== VT_CONST
) {
4369 /* global scope: see if already defined */
4373 if (!is_compatible_types(sym
->t
, u
))
4374 error("incompatible types for redefinition of '%s'",
4375 get_tok_str(v
, NULL
));
4376 if (!(sym
->t
& VT_FORWARD
))
4377 error("redefinition of '%s'", get_tok_str(v
, NULL
));
4378 greloc_patch(sym
, addr
);
4381 sym_push(v
, u
, addr
);
4395 /* put all global symbols in the extern stack and do all the
4396 resolving which can be done without using external symbols from DLLs */
4397 /* XXX: could try to verify types, but would not to save them in
4399 void resolve_global_syms(void)
4401 Sym
*s
, *s1
, *ext_sym
;
4404 s
= global_stack
.top
;
4407 /* do not save static or typedefed symbols or types */
4408 if (!(s
->t
& (VT_STATIC
| VT_TYPEDEF
)) &&
4409 !(s
->v
& (SYM_FIELD
| SYM_STRUCT
)) &&
4410 (s
->v
< SYM_FIRST_ANOM
)) {
4411 ext_sym
= sym_find1(&extern_stack
, s
->v
);
4413 /* if the symbol do not exist, we simply save it */
4414 sym_push1(&extern_stack
, s
->v
, s
->t
, s
->c
);
4415 } else if (ext_sym
->t
& VT_FORWARD
) {
4416 /* external symbol already exists, but only as forward
4418 if (!(s
->t
& VT_FORWARD
)) {
4419 /* s is not forward, so we can relocate all symbols */
4420 greloc_patch(ext_sym
, s
->c
);
4422 /* the two symbols are forward: merge them */
4423 p
= (Reloc
**)&ext_sym
->c
;
4429 /* external symbol already exists and is defined :
4430 patch all references to it */
4431 if (!(s
->t
& VT_FORWARD
))
4432 error("'%s' defined twice", get_tok_str(s
->v
, NULL
));
4433 greloc_patch(s
, ext_sym
->c
);
4440 /* compile a C file. Return non zero if errors. */
4441 int tcc_compile_file(const char *filename1
)
4445 filename
= (char *)filename1
;
4449 file
= fopen(filename
, "r");
4451 error("file '%s' not found", filename
);
4452 include_stack_ptr
= include_stack
;
4453 ifdef_stack_ptr
= ifdef_stack
;
4456 anon_sym
= SYM_FIRST_ANOM
;
4458 define_start
= define_stack
.top
;
4460 ch
= '\n'; /* needed to parse correctly first preprocessor command */
4464 expect("declaration");
4467 /* reset define stack, but leave -Dsymbols (may be incorrect if
4468 they are undefined) */
4469 sym_pop(&define_stack
, define_start
);
4471 resolve_global_syms();
4473 sym_pop(&global_stack
, NULL
);
4478 /* open a dynamic library so that its symbol are available for
4479 compiled programs */
4480 void open_dll(char *libname
)
4485 snprintf(buf
, sizeof(buf
), "lib%s.so", libname
);
4486 h
= dlopen(buf
, RTLD_GLOBAL
| RTLD_LAZY
);
4488 error((char *)dlerror());
4491 void resolve_extern_syms(void)
4497 s
= extern_stack
.top
;
4500 if (s
->t
& VT_FORWARD
) {
4501 /* if there is at least one relocation to do, then find it
4504 str
= get_tok_str(s
->v
, NULL
);
4505 addr
= (int)dlsym(NULL
, str
);
4507 error("unresolved external reference '%s'", str
);
4508 greloc_patch(s
, addr
);
4515 /* output a binary file (for testing) */
4516 void build_exe(char *filename
)
4519 f
= fopen(filename
, "w");
4520 fwrite((void *)prog
, 1, ind
- prog
, f
);
4524 int main(int argc
, char **argv
)
4528 char *p
, *r
, *outfile
;
4531 include_paths
[0] = "/usr/include";
4532 include_paths
[1] = "/usr/lib/tcc";
4533 include_paths
[2] = "/usr/local/lib/tcc";
4534 nb_include_paths
= 3;
4536 /* add all tokens */
4537 tok_ident
= TOK_IDENT
;
4538 p
= "int\0void\0char\0if\0else\0while\0break\0return\0for\0extern\0static\0unsigned\0goto\0do\0continue\0switch\0case\0const\0volatile\0long\0register\0signed\0auto\0inline\0restrict\0float\0double\0_Bool\0short\0struct\0union\0typedef\0default\0enum\0sizeof\0define\0include\0ifdef\0ifndef\0elif\0endif\0defined\0undef\0error\0line\0__LINE__\0__FILE__\0__DATE__\0__TIME__\0__VA_ARGS__\0__func__\0main\0";
4542 tok_alloc(p
, r
- p
- 1);
4546 /* standard defines */
4547 define_symbol("__STDC__");
4549 define_symbol("__i386__");
4551 /* tiny C specific defines */
4552 define_symbol("__TINYC__");
4554 glo
= (int)malloc(DATA_SIZE
);
4555 memset((void *)glo
, 0, DATA_SIZE
);
4556 prog
= (int)malloc(TEXT_SIZE
);
4562 if (optind
>= argc
) {
4564 printf("tcc version 0.9.2 - Tiny C Compiler - Copyright (C) 2001 Fabrice Bellard\n"
4565 "usage: tcc [-Idir] [-Dsym] [-llib] [-i infile] infile [infile_args...]\n");
4573 if (nb_include_paths
>= INCLUDE_PATHS_MAX
)
4574 error("too many include paths");
4575 include_paths
[nb_include_paths
++] = r
+ 2;
4576 } else if (r
[1] == 'D') {
4577 define_symbol(r
+ 2);
4578 } else if (r
[1] == 'l') {
4580 } else if (r
[1] == 'i') {
4583 tcc_compile_file(argv
[optind
++]);
4584 } else if (r
[1] == 'o') {
4585 /* currently, only for testing, so not documented */
4588 outfile
= argv
[optind
++];
4590 fprintf(stderr
, "invalid option -- '%s'\n", r
);
4595 tcc_compile_file(argv
[optind
]);
4597 resolve_extern_syms();
4603 s
= sym_find1(&extern_stack
, TOK_MAIN
);
4604 if (!s
|| (s
->t
& VT_FORWARD
))
4605 error("main() not defined");
4606 t
= (int (*)())s
->c
;
4607 return (*t
)(argc
- optind
, argv
+ optind
);