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 r
; /* associated register */
83 int c
; /* associated number */
84 struct Sym
*next
; /* next related symbol */
85 struct Sym
*prev
; /* prev symbol in stack */
86 struct Sym
*hash_next
; /* next symbol in hash table */
89 typedef struct SymStack
{
91 struct Sym
*hash
[SYM_HASH_SIZE
];
94 /* relocation entry (currently only used for functions or variables */
95 typedef struct Reloc
{
96 int type
; /* type of relocation */
97 int addr
; /* address of relocation */
98 struct Reloc
*next
; /* next relocation */
101 #define RELOC_ADDR32 1 /* 32 bits relocation */
102 #define RELOC_REL32 2 /* 32 bits relative relocation */
105 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
106 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
107 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
109 #define FUNC_NEW 1 /* ansi function prototype */
110 #define FUNC_OLD 2 /* old function prototype */
111 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
113 /* field 'Sym.t' for macros */
114 #define MACRO_OBJ 0 /* object like macro */
115 #define MACRO_FUNC 1 /* function like macro */
117 /* type_decl() types */
118 #define TYPE_ABSTRACT 1 /* type without variable */
119 #define TYPE_DIRECT 2 /* type with variable */
130 int ch
, ch1
, tok
, tok1
;
133 /* loc : local variable index
134 glo : global variable index
135 ind : output code ptr
138 anon_sym: anonymous symbol index
141 prog
, ind
, loc
, glo
, const_wanted
;
142 int global_expr
; /* true if compound literals must be allocated
143 globally (used during initializers parsing */
144 int func_vt
, func_vc
; /* current function return type (used by
145 return instruction) */
147 TokenSym
**table_ident
;
148 TokenSym
*hash_ident
[TOK_HASH_SIZE
];
149 char token_buf
[STRING_MAX_SIZE
+ 1];
150 char *filename
, *funcname
;
151 /* contains global symbols which remain between each translation unit */
152 SymStack extern_stack
;
153 SymStack define_stack
, global_stack
, local_stack
, label_stack
;
155 SValue vstack
[VSTACK_SIZE
], *vtop
;
156 int *macro_ptr
, *macro_ptr_allocated
;
157 IncludeFile include_stack
[INCLUDE_STACK_SIZE
], *include_stack_ptr
;
158 int ifdef_stack
[IFDEF_STACK_SIZE
], *ifdef_stack_ptr
;
159 char *include_paths
[INCLUDE_PATHS_MAX
];
160 int nb_include_paths
;
162 /* use GNU C extensions */
165 /* use Tiny C extensions */
168 /* The current value can be: */
169 #define VT_VALMASK 0x00ff
170 #define VT_CONST 0x00f0 /* constant in vc
171 (must be first non register value) */
172 #define VT_LLOCAL 0x00f1 /* lvalue, offset on stack */
173 #define VT_LOCAL 0x00f2 /* offset on stack */
174 #define VT_CMP 0x00f3 /* the value is stored in processor flags (in vc) */
175 #define VT_JMP 0x00f4 /* value is the consequence of jmp true (even) */
176 #define VT_JMPI 0x00f5 /* value is the consequence of jmp false (odd) */
177 #define VT_LVAL 0x0100 /* var is an lvalue */
178 #define VT_FORWARD 0x0200 /* value is forward reference */
181 #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
183 #define VT_INT 0 /* integer type */
184 #define VT_BYTE 1 /* signed byte type */
185 #define VT_SHORT 2 /* short type */
186 #define VT_VOID 3 /* void type */
187 #define VT_PTR 4 /* pointer increment */
188 #define VT_ENUM 5 /* enum definition */
189 #define VT_FUNC 6 /* function type */
190 #define VT_STRUCT 7 /* struct/union definition */
191 #define VT_FLOAT 8 /* IEEE float */
192 #define VT_DOUBLE 9 /* IEEE double */
193 #define VT_LDOUBLE 10 /* IEEE long double */
194 #define VT_BOOL 11 /* ISOC99 boolean type */
195 #define VT_LLONG 12 /* 64 bit integer */
196 #define VT_LONG 13 /* long integer (NEVER USED as type, only
198 #define VT_BTYPE 0x000f /* mask for basic type */
199 #define VT_UNSIGNED 0x0010 /* unsigned type */
200 #define VT_ARRAY 0x0020 /* array type (also has VT_PTR) */
201 #define VT_BITFIELD 0x0040 /* bitfield modifier */
204 #define VT_EXTERN 0x00000080 /* extern definition */
205 #define VT_STATIC 0x00000100 /* static variable */
206 #define VT_TYPEDEF 0x00000200 /* typedef definition */
208 /* type mask (except storage) */
209 #define VT_TYPE (~(VT_EXTERN | VT_STATIC | VT_TYPEDEF))
213 /* warning: the following compare tokens depend on i386 asm code */
225 #define TOK_LAND 0xa0
229 #define TOK_MID 0xa3 /* inc/dec, to void constant */
231 #define TOK_ARROW 0xa7
232 #define TOK_DOTS 0xa8 /* three dots */
233 #define TOK_SHR 0xa9 /* unsigned shift right */
234 #define TOK_UDIV 0xb0 /* unsigned division */
235 #define TOK_UMOD 0xb1 /* unsigned modulo */
236 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
237 #define TOK_NUM 0xb3 /* number in tokc */
238 #define TOK_CCHAR 0xb4 /* char constant in tokc */
239 #define TOK_STR 0xb5 /* pointer to string in tokc */
240 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
241 #define TOK_LCHAR 0xb7
242 #define TOK_LSTR 0xb8
243 #define TOK_CFLOAT 0xb9 /* float constant */
244 #define TOK_CDOUBLE 0xc0 /* double constant */
245 #define TOK_CLDOUBLE 0xc1 /* long double constant */
247 #define TOK_SHL 0x01 /* shift left */
248 #define TOK_SAR 0x02 /* signed shift right */
250 /* assignement operators : normal operator or 0x80 */
251 #define TOK_A_MOD 0xa5
252 #define TOK_A_AND 0xa6
253 #define TOK_A_MUL 0xaa
254 #define TOK_A_ADD 0xab
255 #define TOK_A_SUB 0xad
256 #define TOK_A_DIV 0xaf
257 #define TOK_A_XOR 0xde
258 #define TOK_A_OR 0xfc
259 #define TOK_A_SHL 0x81
260 #define TOK_A_SAR 0x82
262 /* all identificators and strings have token above that */
263 #define TOK_IDENT 256
284 /* ignored types Must have contiguous values */
294 /* unsupported type */
307 /* preprocessor only */
308 TOK_UIDENT
, /* first "user" ident (not keyword) */
309 TOK_DEFINE
= TOK_UIDENT
,
325 /* special identifiers */
330 /* XXX: need to define this to use them in non ISOC99 context */
331 extern float strtof (const char *__nptr
, char **__endptr
);
332 extern long double strtold (const char *__nptr
, char **__endptr
);
336 void next_nomacro(void);
337 int expr_const(void);
341 void decl_initializer(int t
, int r
, int c
, int first
, int size_only
);
342 int decl_initializer_alloc(int t
, int sec
, int has_init
);
344 void move_reg(int r
, int s
);
345 void save_reg(int r
);
351 void macro_subst(int **tok_str
, int *tok_len
,
352 Sym
**nested_list
, int *macro_str
);
353 int save_reg_forced(int r
);
355 void gen_cast(int t
);
357 int type_size(int t
, int *a
);
358 int pointed_type(int t
);
359 int pointed_size(int t
);
360 int parse_btype(int *type_ptr
);
361 int type_decl(int *v
, int t
, int td
);
362 void error(const char *fmt
, ...);
363 void vset(int t
, int r
, int v
);
365 /* true if float/double/long double type */
366 static inline int is_float(int t
)
370 return bt
== VT_LDOUBLE
|| bt
== VT_DOUBLE
|| bt
== VT_FLOAT
;
373 #include "i386-gen.c"
375 #ifdef CONFIG_TCC_STATIC
377 #define RTLD_LAZY 0x001
378 #define RTLD_NOW 0x002
379 #define RTLD_GLOBAL 0x100
381 /* dummy function for profiling */
382 void *dlopen(const char *filename
, int flag
)
387 const char *dlerror(void)
392 typedef struct TCCSyms
{
397 #define TCCSYM(a) { #a, &a, },
399 /* add the symbol you want here if no dynamic linking is done */
400 static TCCSyms tcc_syms
[] = {
408 void *dlsym(void *handle
, char *symbol
)
412 while (p
->str
!= NULL
) {
413 if (!strcmp(p
->str
, symbol
))
422 static inline int isid(int c
)
424 return (c
>= 'a' && c
<= 'z') ||
425 (c
>= 'A' && c
<= 'Z') ||
429 static inline int isnum(int c
)
431 return c
>= '0' & c
<= '9';
434 static inline int toup(int c
)
436 if (ch
>= 'a' && ch
<= 'z')
437 return ch
- 'a' + 'A';
445 for(f
= include_stack
; f
< include_stack_ptr
; f
++)
446 fprintf(stderr
, "In file included from %s:%d:\n",
447 f
->filename
, f
->line_num
);
448 fprintf(stderr
, "%s:%d: ", filename
, line_num
);
451 void error(const char *fmt
, ...)
456 vfprintf(stderr
, fmt
, ap
);
457 fprintf(stderr
, "\n");
462 void expect(const char *msg
)
464 error("%s expected", msg
);
467 void warning(const char *fmt
, ...)
473 fprintf(stderr
, "warning: ");
474 vfprintf(stderr
, fmt
, ap
);
475 fprintf(stderr
, "\n");
482 error("'%c' expected", c
);
486 void test_lvalue(void)
488 if (!(vtop
->r
& VT_LVAL
))
492 TokenSym
*tok_alloc(char *str
, int len
)
494 TokenSym
*ts
, **pts
, **ptable
;
501 h
= ((h
<< 8) | (str
[i
] & 0xff)) % TOK_HASH_SIZE
;
503 pts
= &hash_ident
[h
];
508 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
510 pts
= &(ts
->hash_next
);
513 if (tok_ident
>= SYM_FIRST_ANOM
)
514 error("memory full");
516 /* expand token table if needed */
517 i
= tok_ident
- TOK_IDENT
;
518 if ((i
% TOK_ALLOC_INCR
) == 0) {
519 ptable
= realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
521 error("memory full");
522 table_ident
= ptable
;
525 ts
= malloc(sizeof(TokenSym
) + len
);
527 error("memory full");
529 ts
->tok
= tok_ident
++;
531 ts
->hash_next
= NULL
;
532 memcpy(ts
->str
, str
, len
+ 1);
537 void add_char(char **pp
, int c
)
541 if (c
== '\'' || c
== '\"' || c
== '\\') {
542 /* XXX: could be more precise if char or string */
545 if (c
>= 32 && c
<= 126) {
552 *p
++ = '0' + ((c
>> 6) & 7);
553 *p
++ = '0' + ((c
>> 3) & 7);
554 *p
++ = '0' + (c
& 7);
560 /* XXX: buffer overflow */
561 char *get_tok_str(int v
, CValue
*cv
)
563 static char buf
[STRING_MAX_SIZE
+ 1];
569 sprintf(buf
, "%u", cv
->ui
);
571 } else if (v
== TOK_CCHAR
|| v
== TOK_LCHAR
) {
578 } else if (v
== TOK_STR
|| v
== TOK_LSTR
) {
582 for(i
=0;i
<ts
->len
;i
++)
583 add_char(&p
, ts
->str
[i
]);
587 } else if (v
< TOK_IDENT
) {
592 } else if (v
< tok_ident
) {
593 return table_ident
[v
- TOK_IDENT
]->str
;
595 /* should never happen */
600 /* push, without hashing */
601 Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
604 s
= malloc(sizeof(Sym
));
606 error("memory full");
617 /* find a symbol and return its associated structure. 's' is the top
618 of the symbol stack */
619 Sym
*sym_find2(Sym
*s
, int v
)
629 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
631 /* find a symbol and return its associated structure. 'st' is the
633 Sym
*sym_find1(SymStack
*st
, int v
)
637 s
= st
->hash
[HASH_SYM(v
)];
646 Sym
*sym_push1(SymStack
*st
, int v
, int t
, int c
)
649 s
= sym_push2(&st
->top
, v
, t
, c
);
650 /* add in hash table */
652 ps
= &st
->hash
[HASH_SYM(v
)];
659 /* find a symbol in the right symbol space */
663 s
= sym_find1(&local_stack
, v
);
665 s
= sym_find1(&global_stack
, v
);
669 /* push a given symbol on the symbol stack */
670 Sym
*sym_push(int v
, int t
, int r
, int c
)
674 s
= sym_push1(&local_stack
, v
, t
, c
);
676 s
= sym_push1(&global_stack
, v
, t
, c
);
681 /* pop symbols until top reaches 'b' */
682 void sym_pop(SymStack
*st
, Sym
*b
)
689 /* free hash table entry, except if symbol was freed (only
690 used for #undef symbols) */
692 st
->hash
[HASH_SYM(s
->v
)] = s
->hash_next
;
699 /* undefined a hashed symbol (used for #undef). Its name is set to
701 void sym_undef(SymStack
*st
, Sym
*s
)
704 ss
= &st
->hash
[HASH_SYM(s
->v
)];
705 while (*ss
!= NULL
) {
708 ss
= &(*ss
)->hash_next
;
714 /* no need to put that inline */
717 if (include_stack_ptr
== include_stack
)
719 /* pop include stack */
723 file
= include_stack_ptr
->file
;
724 filename
= include_stack_ptr
->filename
;
725 line_num
= include_stack_ptr
->line_num
;
729 /* read next char from current input file */
730 static inline void inp(void)
733 /* faster than fgetc */
734 ch1
= getc_unlocked(file
);
736 if (handle_eof() < 0)
743 // printf("ch1=%c 0x%x\n", ch1, ch1);
746 /* input with '\\n' handling */
747 static inline void minp(void)
752 if (ch
== '\\' && ch1
== '\n') {
756 //printf("ch=%c 0x%x\n", ch, ch);
760 /* same as minp, but also skip comments */
768 /* single line C++ comments */
770 while (ch1
!= '\n' && ch1
!= -1)
773 ch
= ' '; /* return space */
774 } else if (ch1
== '*') {
780 if (c
== '*' && ch1
== '/') {
782 ch
= ' '; /* return space */
794 void skip_spaces(void)
796 while (ch
== ' ' || ch
== '\t')
800 /* skip block of text until #else, #elif or #endif. skip also pairs of
802 void preprocess_skip()
818 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
820 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
822 else if (tok
== TOK_ENDIF
)
828 /* return the number of additionnal 'ints' necessary to store the
830 static inline int tok_ext_size(int t
)
844 return LDOUBLE_SIZE
/ 4;
850 void tok_add(int **tok_str
, int *tok_len
, int t
)
855 if ((len
& 63) == 0) {
856 str
= realloc(str
, (len
+ 64) * sizeof(int));
865 void tok_add2(int **tok_str
, int *tok_len
, int t
, CValue
*cv
)
869 tok_add(tok_str
, tok_len
, t
);
872 tok_add(tok_str
, tok_len
, cv
->tab
[i
]);
875 /* get a token from an integer array and increment pointer accordingly */
876 int tok_get(int **tok_str
, CValue
*cv
)
889 /* eval an expression for #if/#elif */
890 int expr_preprocess(void)
900 next(); /* do macro subst */
901 if (tok
== TOK_DEFINED
) {
906 c
= sym_find1(&define_stack
, tok
) != 0;
911 } else if (tok
>= TOK_IDENT
) {
912 /* if undefined macro */
916 tok_add2(&str
, &len
, tok
, &tokc
);
918 tok_add(&str
, &len
, -1); /* simulate end of file */
919 tok_add(&str
, &len
, 0);
920 /* now evaluate C constant expression */
930 void tok_print(int *str
)
936 t
= tok_get(&str
, &cval
);
939 printf(" %s", get_tok_str(t
, &cval
));
945 /* XXX: should be more factorized */
946 void define_symbol(char *sym
)
952 ts
= tok_alloc(sym
, 0);
956 tok_add2(&str
, &len
, TOK_NUM
, &cval
);
957 tok_add(&str
, &len
, 0);
958 sym_push1(&define_stack
, ts
->tok
, MACRO_OBJ
, (int)str
);
961 void preprocess(void)
963 int size
, i
, c
, v
, t
, *str
, len
;
964 char buf
[1024], *q
, *p
;
967 Sym
**ps
, *first
, *s
;
972 if (tok
== TOK_DEFINE
) {
975 /* XXX: should check if same macro (ANSI) */
978 /* '(' must be just after macro definition for MACRO_FUNC */
985 tok
= TOK___VA_ARGS__
;
986 s
= sym_push1(&define_stack
, tok
| SYM_FIELD
, 0, 0);
1000 if (ch
== '\n' || ch
== -1)
1003 tok_add2(&str
, &len
, tok
, &tokc
);
1005 tok_add(&str
, &len
, 0);
1007 printf("define %s %d: ", get_tok_str(v
, NULL
), t
);
1010 s
= sym_push1(&define_stack
, v
, t
, (int)str
);
1012 } else if (tok
== TOK_UNDEF
) {
1014 s
= sym_find1(&define_stack
, tok
);
1015 /* undefine symbol by putting an invalid name */
1017 sym_undef(&define_stack
, s
);
1018 } else if (tok
== TOK_INCLUDE
) {
1023 } else if (ch
== '\"') {
1028 while (ch
!= c
&& ch
!= '\n' && ch
!= -1) {
1029 if ((q
- buf
) < sizeof(buf
) - 1)
1037 error("#include syntax error");
1038 /* XXX: buffer overflow */
1039 strcpy(buf
, get_tok_str(tok
, &tokc
));
1042 /* eat all spaces and comments after include */
1043 /* XXX: slightly incorrect */
1044 while (ch1
!= '\n' && ch1
!= -1)
1047 if (include_stack_ptr
>= include_stack
+ INCLUDE_STACK_SIZE
)
1048 error("memory full");
1050 /* first search in current dir if "header.h" */
1051 /* XXX: buffer overflow */
1053 p
= strrchr(filename
, '/');
1055 size
= p
+ 1 - filename
;
1056 memcpy(buf1
, filename
, size
);
1059 f
= fopen(buf1
, "r");
1063 /* now search in standard include path */
1064 for(i
=nb_include_paths
- 1;i
>=0;i
--) {
1065 strcpy(buf1
, include_paths
[i
]);
1068 f
= fopen(buf1
, "r");
1072 error("include file '%s' not found", buf1
);
1075 /* push current file in stack */
1076 /* XXX: fix current line init */
1077 include_stack_ptr
->file
= file
;
1078 include_stack_ptr
->filename
= filename
;
1079 include_stack_ptr
->line_num
= line_num
;
1080 include_stack_ptr
++;
1082 filename
= strdup(buf1
);
1084 } else if (tok
== TOK_IFNDEF
) {
1087 } else if (tok
== TOK_IF
) {
1088 c
= expr_preprocess();
1090 } else if (tok
== TOK_IFDEF
) {
1094 c
= (sym_find1(&define_stack
, tok
) != 0) ^ c
;
1096 if (ifdef_stack_ptr
>= ifdef_stack
+ IFDEF_STACK_SIZE
)
1097 error("memory full");
1098 *ifdef_stack_ptr
++ = c
;
1100 } else if (tok
== TOK_ELSE
) {
1101 if (ifdef_stack_ptr
== ifdef_stack
||
1102 (ifdef_stack_ptr
[-1] & 2))
1103 error("#else after #else");
1104 c
= (ifdef_stack_ptr
[-1] ^= 3);
1106 } else if (tok
== TOK_ELIF
) {
1107 if (ifdef_stack_ptr
== ifdef_stack
||
1108 ifdef_stack_ptr
[-1] > 1)
1109 error("#elif after #else");
1110 c
= expr_preprocess();
1111 ifdef_stack_ptr
[-1] = c
;
1117 } else if (tok
== TOK_ENDIF
) {
1118 if (ifdef_stack_ptr
== ifdef_stack
)
1121 } else if (tok
== TOK_LINE
) {
1131 /* XXX: potential memory leak */
1132 filename
= strdup(get_tok_str(tok
, &tokc
));
1134 } else if (tok
== TOK_ERROR
) {
1137 /* ignore other preprocess commands or #! for C scripts */
1138 while (ch
!= '\n' && ch
!= -1)
1142 /* read a number in base b */
1148 if (ch
>= 'a' & ch
<= 'f')
1150 else if (ch
>= 'A' & ch
<= 'F')
1164 /* read a character for string or char constant and eval escape codes */
1173 /* at most three octal digits */
1177 c
= c
* 8 + ch
- '0';
1180 c
= c
* 8 + ch
- '0';
1185 } else if (ch
== 'x') {
1203 else if (ch
== 'e' && gnu_ext
)
1205 else if (ch
== '\'' || ch
== '\"' || ch
== '\\' || ch
== '?')
1208 error("invalid escaped char");
1215 /* we use 64 bit numbers */
1218 /* bn = (bn << shift) | or_val */
1219 void bn_lshift(unsigned int *bn
, int shift
, int or_val
)
1223 for(i
=0;i
<BN_SIZE
;i
++) {
1225 bn
[i
] = (v
<< shift
) | or_val
;
1226 or_val
= v
>> (32 - shift
);
1230 void bn_zero(unsigned int *bn
)
1233 for(i
=0;i
<BN_SIZE
;i
++) {
1238 void parse_number(void)
1240 int b
, t
, shift
, frac_bits
, s
, exp_val
;
1243 unsigned int bn
[BN_SIZE
];
1253 /* special dot handling */
1254 if (ch
>= '0' && ch
<= '9') {
1255 goto float_frac_parse
;
1256 } else if (ch
== '.') {
1267 } else if (t
== '0') {
1268 if (ch
== 'x' || ch
== 'X') {
1272 } else if (tcc_ext
&& (ch
== 'b' || ch
== 'B')) {
1278 /* parse all digits. cannot check octal numbers at this stage
1279 because of floating point constants */
1281 if (ch
>= 'a' & ch
<= 'f')
1283 else if (ch
>= 'A' & ch
<= 'F')
1291 if (q
>= token_buf
+ STRING_MAX_SIZE
) {
1293 error("number too long");
1299 ((ch
== 'e' || ch
== 'E') && b
== 10) ||
1300 ((ch
== 'p' || ch
== 'P') && (b
== 16 || b
== 2))) {
1302 /* NOTE: strtox should support that for hexa numbers, but
1303 non ISOC99 libcs do not support it, so we prefer to do
1305 /* hexadecimal or binary floats */
1306 /* XXX: handle overflows */
1318 } else if (t
>= 'a') {
1320 } else if (t
>= 'A') {
1325 bn_lshift(bn
, shift
, t
);
1332 if (t
>= 'a' && t
<= 'f') {
1334 } else if (t
>= 'A' && t
<= 'F') {
1336 } else if (t
>= '0' && t
<= '9') {
1342 error("invalid digit");
1343 bn_lshift(bn
, shift
, t
);
1348 if (ch
!= 'p' && ch
!= 'P')
1349 error("exponent expected");
1355 } else if (ch
== '-') {
1359 if (ch
< '0' || ch
> '9')
1360 error("exponent digits expected");
1361 while (ch
>= '0' && ch
<= '9') {
1362 exp_val
= exp_val
* 10 + ch
- '0';
1365 exp_val
= exp_val
* s
;
1367 /* now we can generate the number */
1368 /* XXX: should patch directly float number */
1369 d
= (double)bn
[1] * 4294967296.0 + (double)bn
[0];
1370 d
= ldexp(d
, exp_val
- frac_bits
);
1375 /* float : should handle overflow */
1377 } else if (t
== 'L') {
1380 /* XXX: not large enough */
1381 tokc
.ld
= (long double)d
;
1387 /* decimal floats */
1389 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1394 while (ch
>= '0' && ch
<= '9') {
1395 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1401 if (ch
== 'e' || ch
== 'E') {
1402 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1406 if (ch
== '-' || ch
== '+') {
1407 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1412 if (ch
< '0' || ch
> '9')
1413 error("exponent digits expected");
1414 while (ch
>= '0' && ch
<= '9') {
1415 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1427 tokc
.f
= strtof(token_buf
, NULL
);
1428 } else if (t
== 'L') {
1431 tokc
.ld
= strtold(token_buf
, NULL
);
1434 tokc
.d
= strtod(token_buf
, NULL
);
1438 /* integer number */
1441 if (b
== 10 && *q
== '0') {
1448 /* no need for checks except for base 10 / 8 errors */
1451 } else if (t
>= 'a') {
1453 } else if (t
>= 'A') {
1458 error("invalid digit");
1462 /* detect overflow */
1464 error("integer constant overflow");
1468 /* XXX: add unsigned constant support (ANSI) */
1469 while (ch
== 'L' || ch
== 'l' || ch
== 'U' || ch
== 'u')
1475 /* return next token without macro substitution */
1476 void next_nomacro1(void)
1484 while (ch
== '\n') {
1486 while (ch
== ' ' || ch
== 9)
1489 /* preprocessor command if # at start of line after
1494 if (ch
!= ' ' && ch
!= '\t' && ch
!= '\f')
1512 while (isid(ch
) || isnum(ch
)) {
1513 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1514 error("ident too long");
1519 ts
= tok_alloc(token_buf
, q
- token_buf
);
1521 } else if (isnum(ch
) || ch
== '.') {
1523 } else if (ch
== '\'') {
1531 } else if (ch
== '\"') {
1536 while (ch
!= '\"') {
1539 error("unterminated string");
1540 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1541 error("string too long");
1545 tokc
.ts
= tok_alloc(token_buf
, q
- token_buf
);
1548 q
= "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\247..\250##\266";
1553 if (*q
== tok
&& q
[1] == ch
) {
1556 /* three chars tests */
1557 if (tok
== TOK_SHL
| tok
== TOK_SAR
) {
1562 } else if (tok
== TOK_DOTS
) {
1564 error("parse error");
1571 /* single char substitutions */
1574 else if (tok
== '>')
1579 /* return next token without macro substitution. Can read input from
1586 tok
= tok_get(¯o_ptr
, &tokc
);
1592 /* substitute args in macro_str and return allocated string */
1593 int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
1595 int *st
, last_tok
, t
, notfirst
, *str
, len
;
1604 t
= tok_get(¯o_str
, &cval
);
1609 t
= tok_get(¯o_str
, &cval
);
1612 s
= sym_find2(args
, t
);
1614 token_buf
[0] = '\0';
1616 /* XXX: buffer overflow */
1620 strcat(token_buf
, " ");
1621 t
= tok_get(&st
, &cval
);
1622 strcat(token_buf
, get_tok_str(t
, &cval
));
1626 printf("stringize: %s\n", token_buf
);
1629 ts
= tok_alloc(token_buf
, 0);
1631 tok_add2(&str
, &len
, TOK_STR
, &cval
);
1633 tok_add2(&str
, &len
, t
, &cval
);
1635 } else if (t
>= TOK_IDENT
) {
1636 s
= sym_find2(args
, t
);
1639 /* if '##' is present before or after , no arg substitution */
1640 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
1642 tok_add(&str
, &len
, *st
++);
1644 macro_subst(&str
, &len
, nested_list
, st
);
1647 tok_add(&str
, &len
, t
);
1650 tok_add2(&str
, &len
, t
, &cval
);
1654 tok_add(&str
, &len
, 0);
1658 /* handle the '##' operator */
1659 int *macro_twosharps(int *macro_str
)
1662 int *macro_str1
, macro_str1_len
, *macro_ptr1
;
1674 while (*macro_ptr
== TOK_TWOSHARPS
) {
1676 macro_ptr1
= macro_ptr
;
1679 t
= tok_get(¯o_ptr
, &cval
);
1680 /* XXX: we handle only most common cases:
1681 ident + ident or ident + number */
1682 if (tok
>= TOK_IDENT
&&
1683 (t
>= TOK_IDENT
|| t
== TOK_NUM
)) {
1684 /* XXX: buffer overflow */
1685 p
= get_tok_str(tok
, &tokc
);
1686 strcpy(token_buf
, p
);
1687 p
= get_tok_str(t
, &cval
);
1688 strcat(token_buf
, p
);
1689 ts
= tok_alloc(token_buf
, 0);
1690 tok
= ts
->tok
; /* modify current token */
1692 /* cannot merge tokens: skip '##' */
1693 macro_ptr
= macro_ptr1
;
1698 tok_add2(¯o_str1
, ¯o_str1_len
, tok
, &tokc
);
1700 tok_add(¯o_str1
, ¯o_str1_len
, 0);
1706 /* do macro substitution of macro_str and add result to
1707 (tok_str,tok_len). If macro_str is NULL, then input stream token is
1708 substituted. 'nested_list' is the list of all macros we got inside
1709 to avoid recursing. */
1710 void macro_subst(int **tok_str
, int *tok_len
,
1711 Sym
**nested_list
, int *macro_str
)
1713 Sym
*s
, *args
, *sa
, *sa1
;
1714 int *str
, parlevel
, len
, *mstr
, t
, *saved_macro_ptr
;
1715 int mstr_allocated
, *macro_str1
;
1718 saved_macro_ptr
= macro_ptr
;
1719 macro_ptr
= macro_str
;
1722 /* first scan for '##' operator handling */
1723 macro_str1
= macro_twosharps(macro_str
);
1724 macro_ptr
= macro_str1
;
1731 /* special macros */
1732 if (tok
== TOK___LINE__
) {
1734 tok_add2(tok_str
, tok_len
, TOK_NUM
, &cval
);
1735 } else if (tok
== TOK___FILE__
) {
1736 cval
.ts
= tok_alloc(filename
, 0);
1737 tok_add2(tok_str
, tok_len
, TOK_STR
, &cval
);
1738 } else if (tok
== TOK___DATE__
) {
1739 cval
.ts
= tok_alloc("Jan 1 1970", 0);
1740 tok_add2(tok_str
, tok_len
, TOK_STR
, &cval
);
1741 } else if (tok
== TOK___TIME__
) {
1742 cval
.ts
= tok_alloc("00:00:00", 0);
1743 tok_add2(tok_str
, tok_len
, TOK_STR
, &cval
);
1744 } else if ((s
= sym_find1(&define_stack
, tok
)) != NULL
) {
1745 /* if symbol is a macro, prepare substitution */
1746 /* if nested substitution, do nothing */
1747 if (sym_find2(*nested_list
, tok
))
1751 if (s
->t
== MACRO_FUNC
) {
1752 /* NOTE: we do not use next_nomacro to avoid eating the
1753 next token. XXX: find better solution */
1757 while (ch
== ' ' || ch
== '\t' || ch
== '\n')
1761 if (t
!= '(') /* no macro subst */
1764 /* argument macro */
1769 while (tok
!= ')' && sa
) {
1773 while ((parlevel
> 0 ||
1776 sa
->v
== (TOK___VA_ARGS__
| SYM_FIELD
)))) &&
1780 else if (tok
== ')')
1782 tok_add2(&str
, &len
, tok
, &tokc
);
1785 tok_add(&str
, &len
, 0);
1786 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, 0, (int)str
);
1794 /* now subst each arg */
1795 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
1806 sym_push2(nested_list
, s
->v
, 0, 0);
1807 macro_subst(tok_str
, tok_len
, nested_list
, mstr
);
1808 /* pop nested defined symbol */
1810 *nested_list
= sa1
->prev
;
1816 /* no need to add if reading input stream */
1819 tok_add2(tok_str
, tok_len
, tok
, &tokc
);
1821 /* only replace one macro while parsing input stream */
1825 macro_ptr
= saved_macro_ptr
;
1830 /* return next token with macro substitution */
1836 /* special 'ungettok' case for label parsing */
1844 /* if not reading from macro substuted string, then try to substitute */
1848 macro_subst(&ptr
, &len
, &nested_list
, NULL
);
1850 tok_add(&ptr
, &len
, 0);
1852 macro_ptr_allocated
= ptr
;
1860 /* end of macro string: free it */
1861 free(macro_ptr_allocated
);
1868 printf("token = %s\n", get_tok_str(tok
, tokc
));
1872 void swap(int *p
, int *q
)
1880 void vsetc(int t
, int r
, CValue
*vc
)
1882 if (vtop
>= vstack
+ VSTACK_SIZE
)
1883 error("memory full");
1884 /* cannot let cpu flags if other instruction are generated */
1885 /* XXX: VT_JMP test too ? */
1886 if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
1894 /* push integer constant */
1899 vsetc(VT_INT
, VT_CONST
, &cval
);
1902 void vset(int t
, int r
, int v
)
1921 if (vtop
>= vstack
+ VSTACK_SIZE
)
1922 error("memory full");
1927 int save_reg_forced(int r
)
1932 /* store register */
1933 loc
= (loc
- 4) & -3;
1935 sv
.r
= VT_LOCAL
| VT_LVAL
;
1940 /* modify all stack values */
1941 for(p
=vstack
;p
<=vtop
;p
++) {
1942 i
= p
->r
& VT_VALMASK
;
1955 /* save r to memory. and mark it as being free */
1956 void save_reg(int r
)
1961 /* modify all stack values */
1962 for(p
=vstack
;p
<=vtop
;p
++) {
1963 i
= p
->r
& VT_VALMASK
;
1971 /* find a free register of class 'rc'. If none, save one register */
1977 /* find a free register */
1978 for(r
=0;r
<NB_REGS
;r
++) {
1979 if (reg_classes
[r
] & rc
) {
1980 for(p
=vstack
;p
<=vtop
;p
++) {
1981 i
= p
->r
& VT_VALMASK
;
1990 /* no register left : free the first one on the stack (very
1991 important to start from the bottom to ensure that we don't
1992 spill registers used in gen_op()) */
1993 for(p
=vstack
;p
<=vtop
;p
++) {
1994 r
= p
->r
& VT_VALMASK
;
1995 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
2003 void save_regs(void)
2008 for(p
=vstack
;p
<=vtop
;p
++) {
2009 r
= p
->r
& VT_VALMASK
;
2016 /* move register 's' to 'r', and flush previous value of r to memory
2018 void move_reg(int r
, int s
)
2031 /* convert a (vtop->t, vtop->c) in register. lvalues are converted as
2032 values. Cannot be used if cannot be converted to register value
2033 (such as structures). */
2036 int r
, bit_pos
, bit_size
, rc
, size
, align
, i
;
2038 /* NOTE: get_reg can modify vstack[] */
2039 if (vtop
->t
& VT_BITFIELD
) {
2040 bit_pos
= (vtop
->t
>> VT_STRUCT_SHIFT
) & 0x3f;
2041 bit_size
= (vtop
->t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
2042 /* remove bit field info to avoid loops */
2043 vtop
->t
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
2044 /* generate shifts */
2045 vpushi(32 - (bit_pos
+ bit_size
));
2047 vpushi(32 - bit_size
);
2048 /* NOTE: transformed to SHR if unsigned */
2052 if (is_float(vtop
->t
) &&
2053 (vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
2054 /* CPUs usually cannot use float constants, so we store them
2055 generically in data segment */
2056 size
= type_size(vtop
->t
, &align
);
2057 glo
= (glo
+ align
- 1) & -align
;
2058 /* XXX: not portable yet */
2061 ((int *)glo
)[i
] = vtop
->c
.tab
[i
];
2066 r
= vtop
->r
& VT_VALMASK
;
2067 if (r
>= VT_CONST
|| (vtop
->r
& VT_LVAL
)) {
2068 if (is_float(vtop
->t
))
2069 rc
= REG_CLASS_FLOAT
;
2080 /* handle constant optimizations and various machine independant opt */
2081 void gen_opc(int op
)
2088 /* currently, we cannot do computations with forward symbols */
2089 c1
= (v1
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
2090 c2
= (v2
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
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;
2098 case '|': v1
->c
.i
|= fc
; break;
2099 case '*': v1
->c
.i
*= fc
; break;
2101 case '/': v1
->c
.i
/= fc
; break; /* XXX: zero case ? */
2102 case '%': v1
->c
.i
%= fc
; break; /* XXX: zero case ? */
2103 case TOK_UDIV
: v1
->c
.i
= (unsigned)v1
->c
.i
/ fc
; break; /* XXX: zero case ? */
2104 case TOK_UMOD
: v1
->c
.i
= (unsigned)v1
->c
.i
% fc
; break; /* XXX: zero case ? */
2105 case TOK_SHL
: v1
->c
.i
<<= fc
; break;
2106 case TOK_SHR
: v1
->c
.i
= (unsigned)v1
->c
.i
>> fc
; break;
2107 case TOK_SAR
: v1
->c
.i
>>= fc
; break;
2109 case TOK_ULT
: v1
->c
.i
= (unsigned)v1
->c
.i
< (unsigned)fc
; break;
2110 case TOK_UGE
: v1
->c
.i
= (unsigned)v1
->c
.i
>= (unsigned)fc
; break;
2111 case TOK_EQ
: v1
->c
.i
= v1
->c
.i
== fc
; break;
2112 case TOK_NE
: v1
->c
.i
= v1
->c
.i
!= fc
; break;
2113 case TOK_ULE
: v1
->c
.i
= (unsigned)v1
->c
.i
<= (unsigned)fc
; break;
2114 case TOK_UGT
: v1
->c
.i
= (unsigned)v1
->c
.i
> (unsigned)fc
; break;
2115 case TOK_LT
: v1
->c
.i
= v1
->c
.i
< fc
; break;
2116 case TOK_GE
: v1
->c
.i
= v1
->c
.i
>= fc
; break;
2117 case TOK_LE
: v1
->c
.i
= v1
->c
.i
<= fc
; break;
2118 case TOK_GT
: v1
->c
.i
= v1
->c
.i
> fc
; break;
2120 case TOK_LAND
: v1
->c
.i
= v1
->c
.i
&& fc
; break;
2121 case TOK_LOR
: v1
->c
.i
= v1
->c
.i
|| fc
; break;
2127 /* if commutative ops, put c2 as constant */
2128 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
2129 op
== '|' || op
== '*')) {
2134 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
2137 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
2138 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
2144 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
2145 /* try to use shifts instead of muls or divs */
2146 if (fc
> 0 && (fc
& (fc
- 1)) == 0) {
2155 else if (op
== TOK_PDIV
)
2163 /* call low level op generator */
2164 /* XXX: remove explicit registers */
2170 int pointed_size(int t
)
2172 return type_size(pointed_type(t
), &t
);
2175 /* generic gen_op: handles types problems */
2178 int u
, t1
, t2
, bt1
, bt2
, t
;
2182 bt1
= t1
& VT_BTYPE
;
2183 bt2
= t2
& VT_BTYPE
;
2185 if (is_float(bt1
) || is_float(bt2
)) {
2186 /* compute bigger type and do implicit casts */
2187 if (bt1
== VT_LDOUBLE
|| bt2
== VT_LDOUBLE
) {
2189 } else if (bt1
== VT_DOUBLE
|| bt2
== VT_DOUBLE
) {
2194 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
2195 op
< TOK_EQ
|| op
> TOK_GT
)
2196 error("invalid operands for binary operation");
2206 if (op
>= TOK_EQ
&& op
<= TOK_GT
) {
2207 /* the result is an int */
2212 } else if (op
== '+' || op
== '-') {
2213 if ((t1
& VT_BTYPE
) == VT_PTR
&&
2214 (t2
& VT_BTYPE
) == VT_PTR
) {
2216 error("invalid type");
2217 /* XXX: check that types are compatible */
2218 u
= pointed_size(t1
);
2220 /* set to integer type */
2224 } else if ((t1
& VT_BTYPE
) == VT_PTR
||
2225 (t2
& VT_BTYPE
) == VT_PTR
) {
2226 if ((t2
& VT_BTYPE
) == VT_PTR
) {
2230 /* stack-4 contains pointer, stack-2 value to add */
2231 vpushi(pointed_size(vtop
[-1].t
));
2234 /* put again type if gen_opc() swaped operands */
2240 /* XXX: test types and compute returned value */
2241 if ((t1
| t2
) & VT_UNSIGNED
||
2242 (t1
& VT_BTYPE
) == VT_PTR
||
2243 (t2
& VT_BTYPE
) == VT_PTR
) {
2250 else if (op
== TOK_LT
)
2252 else if (op
== TOK_GT
)
2254 else if (op
== TOK_LE
)
2256 else if (op
== TOK_GE
)
2263 /* cast 'vtop' to 't' type */
2264 void gen_cast(int t
)
2266 int bits
, sbt
, dbt
, sf
, df
, c
, st1
, dt1
;
2268 /* if not lvalue, then we convert now */
2270 sbt
= vtop
->t
& VT_BTYPE
;
2274 c
= (vtop
->r
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
2276 /* convert from fp to fp */
2278 /* constant case: we can do it now */
2279 /* XXX: in ISOC, cannot do it if error in convert */
2280 if (dbt
== VT_FLOAT
&& sbt
== VT_DOUBLE
)
2281 vtop
->c
.f
= (float)vtop
->c
.d
;
2282 else if (dbt
== VT_FLOAT
&& sbt
== VT_LDOUBLE
)
2283 vtop
->c
.f
= (float)vtop
->c
.ld
;
2284 else if (dbt
== VT_DOUBLE
&& sbt
== VT_FLOAT
)
2285 vtop
->c
.d
= (double)vtop
->c
.f
;
2286 else if (dbt
== VT_DOUBLE
&& sbt
== VT_LDOUBLE
)
2287 vtop
->c
.d
= (double)vtop
->c
.ld
;
2288 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_FLOAT
)
2289 vtop
->c
.ld
= (long double)vtop
->c
.f
;
2290 else if (dbt
== VT_LDOUBLE
&& sbt
== VT_DOUBLE
)
2291 vtop
->c
.ld
= (long double)vtop
->c
.d
;
2293 /* non constant case: generate code */
2297 /* convert int to fp */
2298 /* XXX: add const cases */
2299 st1
= vtop
->t
& (VT_BTYPE
| VT_UNSIGNED
);
2302 case VT_LLONG
| VT_UNSIGNED
:
2304 /* well, currently not needed */
2306 case VT_INT
| VT_UNSIGNED
:
2308 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.ui
; break;
2309 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.ui
; break;
2310 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.ui
; break;
2315 case VT_FLOAT
: vtop
->c
.f
= (float)vtop
->c
.i
; break;
2316 case VT_DOUBLE
: vtop
->c
.d
= (double)vtop
->c
.i
; break;
2317 case VT_LDOUBLE
: vtop
->c
.ld
= (long double)vtop
->c
.i
; break;
2326 /* convert fp to int */
2327 dt1
= t
& (VT_BTYPE
| VT_UNSIGNED
);
2328 /* we handle char/short/etc... with generic code */
2329 if (dt1
!= VT_INT
| VT_UNSIGNED
&&
2330 dt1
!= VT_LLONG
| VT_UNSIGNED
&&
2335 case VT_LLONG
| VT_UNSIGNED
:
2337 /* well, currently not needed */
2339 case VT_INT
| VT_UNSIGNED
:
2341 case VT_FLOAT
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
2342 case VT_DOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
2343 case VT_LDOUBLE
: vtop
->c
.ui
= (unsigned int)vtop
->c
.d
; break;
2349 case VT_FLOAT
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
2350 case VT_DOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
2351 case VT_LDOUBLE
: vtop
->c
.i
= (int)vtop
->c
.d
; break;
2359 if (dt1
== VT_INT
&& (t
& (VT_BTYPE
| VT_UNSIGNED
)) != dt1
) {
2360 /* additionnal cast for char/short/bool... */
2364 } else if (dbt
== VT_BOOL
) {
2367 } else if ((dbt
== VT_BYTE
|| dbt
== VT_SHORT
) &&
2368 !(vtop
->r
& VT_LVAL
)) {
2369 /* no need to apply if lvalue because we do it while
2370 loading the value */
2375 if (t
& VT_UNSIGNED
) {
2376 vpushi((1 << bits
) - 1);
2390 /* return type size. Put alignment at 'a' */
2391 int type_size(int t
, int *a
)
2397 if (bt
== VT_STRUCT
) {
2399 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
2400 *a
= 4; /* XXX: cannot store it yet. Doing that is safe */
2402 } else if (bt
== VT_PTR
) {
2404 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
2405 return type_size(s
->t
, a
) * s
->c
;
2410 } else if (bt
== VT_LDOUBLE
) {
2412 return LDOUBLE_SIZE
;
2413 } else if (bt
== VT_DOUBLE
|| bt
== VT_LLONG
) {
2416 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
2419 } else if (bt
== VT_SHORT
) {
2423 /* char, void, function, _Bool */
2429 /* return the pointed type of t */
2430 int pointed_type(int t
)
2433 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
2434 return s
->t
| (t
& ~VT_TYPE
);
2437 int mk_pointer(int t
)
2441 sym_push(p
, t
, 0, -1);
2442 return VT_PTR
| (p
<< VT_STRUCT_SHIFT
) | (t
& ~VT_TYPE
);
2445 int is_compatible_types(int t1
, int t2
)
2452 bt1
= t1
& VT_BTYPE
;
2453 bt2
= t2
& VT_BTYPE
;
2454 if (bt1
== VT_PTR
) {
2455 t1
= pointed_type(t1
);
2456 /* if function, then convert implicitely to function pointer */
2457 if (bt2
!= VT_FUNC
) {
2460 t2
= pointed_type(t2
);
2462 /* void matches everything */
2465 if (t1
== VT_VOID
|| t2
== VT_VOID
)
2467 return is_compatible_types(t1
, t2
);
2468 } else if (bt1
== VT_STRUCT
) {
2470 } else if (bt1
== VT_FUNC
) {
2473 s1
= sym_find(((unsigned)t1
>> VT_STRUCT_SHIFT
));
2474 s2
= sym_find(((unsigned)t2
>> VT_STRUCT_SHIFT
));
2475 if (!is_compatible_types(s1
->t
, s2
->t
))
2477 /* XXX: not complete */
2478 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
2482 while (s1
!= NULL
) {
2485 if (!is_compatible_types(s1
->t
, s2
->t
))
2494 /* XXX: not complete */
2499 int check_assign_types(int t1
, int t2
)
2503 if ((t1
& VT_BTYPE
) == VT_PTR
&&
2504 (t2
& VT_BTYPE
) == VT_FUNC
) {
2505 return is_compatible_types(pointed_type(t1
), t2
);
2507 return is_compatible_types(t1
, t2
);
2511 /* print a type. If 'varstr' is not NULL, then the variable is also
2512 printed in the type */
2513 /* XXX: add array and function pointers */
2514 /* XXX: buffer overflows */
2515 void type_to_str(char *buf
, int buf_size
,
2516 int t
, const char *varstr
)
2525 if (t
& VT_UNSIGNED
)
2526 strcat(buf
, "unsigned ");
2529 strcat(buf
, "void");
2532 strcat(buf
, "_Bool");
2535 strcat(buf
, "char");
2538 strcat(buf
, "short");
2544 strcat(buf
, "long");
2547 strcat(buf
, "long long");
2550 strcat(buf
, "float");
2553 strcat(buf
, "double");
2556 strcat(buf
, "long double");
2560 if (bt
== VT_STRUCT
)
2561 strcat(buf
, "struct ");
2563 strcat(buf
, "enum ");
2564 v
= (unsigned)t
>> VT_STRUCT_SHIFT
;
2565 if (v
>= SYM_FIRST_ANOM
)
2566 strcat(buf
, "<anonymous>");
2568 strcat(buf
, get_tok_str(v
, NULL
));
2571 s
= sym_find((unsigned)t
>> VT_STRUCT_SHIFT
);
2572 type_to_str(buf
, buf_size
, s
->t
, varstr
);
2575 while (sa
!= NULL
) {
2576 type_to_str(buf1
, sizeof(buf1
), sa
->t
, NULL
);
2585 s
= sym_find((unsigned)t
>> VT_STRUCT_SHIFT
);
2588 strcat(buf1
, varstr
);
2589 type_to_str(buf
, buf_size
, s
->t
, buf1
);
2594 strcat(buf
, varstr
);
2601 /* verify type compatibility to store vtop in 'st' type, and generate
2603 void gen_assign_cast(int dt
)
2606 char buf1
[256], buf2
[256];
2608 st
= vtop
->t
; /* destination type */
2609 if (!check_assign_types(dt
, st
)) {
2610 type_to_str(buf1
, sizeof(buf1
), st
, NULL
);
2611 type_to_str(buf2
, sizeof(buf2
), dt
, NULL
);
2612 error("cannot cast '%s' to '%s'", buf1
, buf2
);
2614 if ((dt
& VT_BTYPE
) == VT_BOOL
|| is_float(dt
)) {
2615 gen_cast(dt
& VT_BTYPE
);
2620 /* store vtop in lvalue pushed on stack */
2623 int ft
, r
, t
, size
, align
, bit_size
, bit_pos
;
2627 gen_assign_cast(ft
& VT_TYPE
);
2629 if ((vtop
->t
& VT_BTYPE
) == VT_STRUCT
) {
2630 /* if structure, only generate pointer */
2631 /* structure assignment : generate memcpy */
2632 /* XXX: optimize if small size */
2637 size
= type_size(vtop
->t
, &align
);
2642 vtop
->r
&= ~VT_LVAL
;
2647 vtop
->r
&= ~VT_LVAL
;
2651 vpushi((int)&memcpy
);
2653 /* leave source on stack */
2654 } else if (ft
& VT_BITFIELD
) {
2655 /* bitfield store handling */
2656 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
2657 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
2658 /* remove bit field info to avoid loops */
2659 vtop
[-1].t
= ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
2661 /* duplicate destination */
2663 vtop
[-1] = vtop
[-2];
2665 /* mask and shift source */
2666 vpushi((1 << bit_size
) - 1);
2670 /* load destination, mask and or with source */
2672 vpushi(~(((1 << bit_size
) - 1) << bit_pos
));
2678 r
= gv(); /* generate value */
2679 /* if lvalue was saved on stack, must read it */
2680 if ((vtop
[-1].r
& VT_VALMASK
) == VT_LLOCAL
) {
2682 t
= get_reg(REG_CLASS_INT
);
2684 sv
.r
= VT_LOCAL
| VT_LVAL
;
2685 sv
.c
.ul
= vtop
[-1].c
.ul
;
2687 vtop
[-1].r
= t
| VT_LVAL
;
2696 /* post defines POST/PRE add. c is the token ++ or -- */
2697 void inc(int post
, int c
)
2704 vdup(); /* room for returned value */
2705 vdup(); /* save lvalue */
2708 /* duplicate value */
2709 /* XXX: handle floats */
2710 r1
= get_reg(REG_CLASS_INT
);
2714 load(r1
, &sv
); /* move r to r1 */
2715 /* duplicates value */
2720 vpushi(c
- TOK_MID
);
2722 vstore(); /* store value */
2724 vpop(); /* if post op, return saved value */
2727 /* enum/struct/union declaration */
2728 int struct_decl(int u
)
2730 int a
, t
, b
, v
, size
, align
, maxalign
, c
, offset
;
2731 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
;
2734 a
= tok
; /* save decl type */
2739 /* struct already defined ? return it */
2740 /* XXX: check consistency */
2741 if (s
= sym_find(v
| SYM_STRUCT
)) {
2743 error("invalid type");
2749 s
= sym_push(v
| SYM_STRUCT
, a
, 0, 0);
2750 /* put struct/union/enum name in type */
2752 u
= u
| (v
<< VT_STRUCT_SHIFT
);
2757 error("struct/union/enum already defined");
2758 /* cannot be empty */
2765 if (a
== TOK_ENUM
) {
2772 /* enum symbols have static storage */
2773 sym_push(v
, VT_STATIC
| VT_INT
, VT_CONST
, c
);
2783 t
= type_decl(&v
, b
, TYPE_DIRECT
);
2784 if ((t
& VT_BTYPE
) == VT_FUNC
||
2785 (t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
)))
2786 error("invalid type for '%s'",
2787 get_tok_str(v
, NULL
));
2793 bit_size
= expr_const();
2794 /* XXX: handle v = 0 case for messages */
2796 error("negative width in bit-field '%s'",
2797 get_tok_str(v
, NULL
));
2798 if (v
&& bit_size
== 0)
2799 error("zero width for bit-field '%s'",
2800 get_tok_str(v
, NULL
));
2802 size
= type_size(t
, &align
);
2804 if (bit_size
>= 0) {
2809 error("bitfields must have scalar type");
2811 if (bit_size
> bsize
) {
2812 error("width of '%s' exceeds its type",
2813 get_tok_str(v
, NULL
));
2814 } else if (bit_size
== bsize
) {
2815 /* no need for bit fields */
2817 } else if (bit_size
== 0) {
2818 /* XXX: what to do if only padding in a
2820 /* zero size: means to pad */
2824 /* we do not have enough room ? */
2825 if ((bit_pos
+ bit_size
) > bsize
)
2828 /* XXX: handle LSB first */
2830 (bit_pos
<< VT_STRUCT_SHIFT
) |
2831 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
2832 bit_pos
+= bit_size
;
2838 /* add new memory data only if starting
2840 if (lbit_pos
== 0) {
2841 if (a
== TOK_STRUCT
) {
2842 c
= (c
+ align
- 1) & -align
;
2850 if (align
> maxalign
)
2854 printf("add field %s offset=%d",
2855 get_tok_str(v
, NULL
), offset
);
2856 if (t
& VT_BITFIELD
) {
2857 printf(" pos=%d size=%d",
2858 (t
>> VT_STRUCT_SHIFT
) & 0x3f,
2859 (t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
2863 ss
= sym_push(v
| SYM_FIELD
, t
, 0, offset
);
2867 if (tok
== ';' || tok
== -1)
2877 /* size for struct/union, dummy for enum */
2878 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
2883 /* return 0 if no type declaration. otherwise, return the basic type
2886 int parse_btype(int *type_ptr
)
2888 int t
, u
, type_found
;
2901 if ((t
& VT_BTYPE
) != 0)
2902 error("too many basic types");
2916 if ((t
& VT_BTYPE
) == VT_DOUBLE
) {
2917 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
2918 } else if ((t
& VT_BTYPE
) == VT_LONG
) {
2919 t
= (t
& ~VT_BTYPE
) | VT_LLONG
;
2933 if ((t
& VT_BTYPE
) == VT_LONG
) {
2934 t
= (t
& ~VT_BTYPE
) | VT_LDOUBLE
;
2941 u
= struct_decl(VT_ENUM
);
2945 u
= struct_decl(VT_STRUCT
);
2948 /* type modifiers */
2978 if (!s
|| !(s
->t
& VT_TYPEDEF
))
2980 t
|= (s
->t
& ~VT_TYPEDEF
);
2987 /* long is never used as type */
2988 if ((t
& VT_BTYPE
) == VT_LONG
)
2989 t
= (t
& ~VT_BTYPE
) | VT_INT
;
2994 int post_type(int t
)
2996 int p
, n
, pt
, l
, t1
;
2997 Sym
**plast
, *s
, *first
;
3000 /* function declaration */
3005 while (tok
!= ')') {
3006 /* read param name and compute offset */
3007 if (l
!= FUNC_OLD
) {
3008 if (!parse_btype(&pt
)) {
3010 error("invalid type");
3017 if ((pt
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
3019 pt
= type_decl(&n
, pt
, TYPE_DIRECT
| TYPE_ABSTRACT
);
3020 if ((pt
& VT_BTYPE
) == VT_VOID
)
3021 error("parameter declared as void");
3028 /* array must be transformed to pointer according to ANSI C */
3030 s
= sym_push(n
| SYM_FIELD
, pt
, 0, 0);
3035 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
3042 /* if no parameters, then old type prototype */
3046 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
3047 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
));
3048 /* we push a anonymous symbol which will contain the function prototype */
3050 s
= sym_push(p
, t
, 0, l
);
3052 t
= t1
| VT_FUNC
| (p
<< VT_STRUCT_SHIFT
);
3053 } else if (tok
== '[') {
3054 /* array definition */
3060 error("invalid array size");
3063 /* parse next post type */
3064 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
3065 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
));
3067 /* we push a anonymous symbol which will contain the array
3070 sym_push(p
, t
, 0, n
);
3071 t
= t1
| VT_ARRAY
| VT_PTR
| (p
<< VT_STRUCT_SHIFT
);
3076 /* Read a type declaration (except basic type), and return the
3077 type. If v is true, then also put variable name in 'vtop->c' */
3078 int type_decl(int *v
, int t
, int td
)
3083 while (tok
== '*') {
3085 while (tok
== TOK_CONST
|| tok
== TOK_VOLATILE
|| tok
== TOK_RESTRICT
)
3090 /* recursive type */
3091 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
3094 u
= type_decl(v
, 0, td
);
3098 /* type identifier */
3099 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
3103 if (!(td
& TYPE_ABSTRACT
))
3104 expect("identifier");
3108 /* append t at the end of u */
3114 s
= sym_find((unsigned)p
>> VT_STRUCT_SHIFT
);
3124 /* define a new external reference to a function 'v' of type 'u' */
3125 Sym
*external_sym(int v
, int u
, int r
)
3130 /* push forward reference */
3131 s
= sym_push1(&global_stack
,
3133 s
->r
= r
| VT_CONST
| VT_FORWARD
;
3140 if (vtop
->r
& VT_LVAL
)
3142 if ((vtop
->t
& VT_BTYPE
) != VT_PTR
)
3144 vtop
->t
= pointed_type(vtop
->t
);
3145 if (!(vtop
->t
& VT_ARRAY
)) /* an array is never an lvalue */
3149 /* pass a parameter to a function and do type checking and casting */
3150 void gfunc_param_typed(GFuncContext
*gf
, Sym
*func
, Sym
*arg
)
3153 func_type
= func
->c
;
3154 if (func_type
== FUNC_OLD
||
3155 (func_type
== FUNC_ELLIPSIS
&& arg
== NULL
)) {
3156 /* default casting : only need to convert float to double */
3157 if ((vtop
->t
& VT_BTYPE
) == VT_FLOAT
)
3158 gen_cast(VT_DOUBLE
);
3159 } else if (arg
== NULL
) {
3160 error("too many arguments to function");
3162 gen_assign_cast(arg
->t
);
3169 int n
, t
, ft
, fc
, p
, align
, size
, r
;
3173 if (tok
== TOK_NUM
|| tok
== TOK_CCHAR
|| tok
== TOK_LCHAR
) {
3176 } else if (tok
== TOK_CFLOAT
) {
3177 vsetc(VT_FLOAT
, VT_CONST
, &tokc
);
3179 } else if (tok
== TOK_CDOUBLE
) {
3180 vsetc(VT_DOUBLE
, VT_CONST
, &tokc
);
3182 } else if (tok
== TOK_CLDOUBLE
) {
3183 vsetc(VT_LDOUBLE
, VT_CONST
, &tokc
);
3185 } else if (tok
== TOK___FUNC__
) {
3186 /* special function name identifier */
3187 /* generate (char *) type */
3188 vset(mk_pointer(VT_BYTE
), VT_CONST
, glo
);
3189 strcpy((void *)glo
, funcname
);
3190 glo
+= strlen(funcname
) + 1;
3192 } else if (tok
== TOK_LSTR
) {
3195 } else if (tok
== TOK_STR
) {
3196 /* string parsing */
3199 type_size(t
, &align
);
3200 glo
= (glo
+ align
- 1) & -align
;
3202 /* we must declare it as an array first to use initializer parser */
3203 t
= VT_ARRAY
| mk_pointer(t
);
3204 decl_initializer(t
, VT_CONST
, glo
, 1, 0);
3205 glo
+= type_size(t
, &align
);
3206 /* put it as pointer */
3207 vset(t
& ~VT_ARRAY
, VT_CONST
, fc
);
3213 if (parse_btype(&t
)) {
3214 ft
= type_decl(&n
, t
, TYPE_ABSTRACT
);
3216 /* check ISOC99 compound literal */
3218 /* data is allocated locally by default */
3223 /* all except arrays are lvalues */
3224 if (!(ft
& VT_ARRAY
))
3226 fc
= decl_initializer_alloc(ft
, r
, 1);
3236 } else if (t
== '*') {
3239 } else if (t
== '&') {
3241 /* functions names must be treated as function pointers,
3242 except for unary '&' and sizeof. Since we consider that
3243 functions are not lvalues, we only have to handle it
3244 there and in function calls. */
3245 if ((vtop
->t
& VT_BTYPE
) != VT_FUNC
)
3247 vtop
->t
= mk_pointer(vtop
->t
);
3248 vtop
->r
&= ~VT_LVAL
;
3252 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
)
3253 vtop
->c
.i
= !vtop
->c
.i
;
3254 else if ((vtop
->r
& VT_VALMASK
) == VT_CMP
)
3255 vtop
->c
.i
= vtop
->c
.i
^ 1;
3257 vset(VT_INT
, VT_JMP
, gtst(1, 0));
3267 if (t
== TOK_SIZEOF
) {
3270 if (parse_btype(&t
)) {
3271 t
= type_decl(&n
, t
, TYPE_ABSTRACT
);
3273 /* XXX: some code could be generated: add eval
3285 vpushi(type_size(t
, &t
));
3287 if (t
== TOK_INC
|| t
== TOK_DEC
) {
3290 } else if (t
== '-') {
3299 error("'%s' undeclared", get_tok_str(t
, NULL
));
3300 /* for simple function calls, we tolerate undeclared
3301 external reference */
3303 sym_push1(&global_stack
, p
, 0, FUNC_OLD
);
3304 /* int() function */
3305 s
= external_sym(t
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
), 0);
3307 vset(s
->t
, s
->r
, s
->c
);
3308 /* if forward reference, we must point to s */
3309 if (vtop
->r
& VT_FORWARD
)
3314 /* post operations */
3316 if (tok
== TOK_INC
| tok
== TOK_DEC
) {
3319 } else if (tok
== '.' | tok
== TOK_ARROW
) {
3321 if (tok
== TOK_ARROW
)
3324 vtop
->r
&= ~VT_LVAL
;
3326 /* expect pointer on structure */
3327 if ((vtop
->t
& VT_BTYPE
) != VT_STRUCT
)
3328 expect("struct or union");
3329 s
= sym_find(((unsigned)vtop
->t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
3332 while (s
= s
->next
) {
3337 error("field not found");
3338 /* add field offset to pointer */
3339 vtop
->t
= VT_INT
; /* change type to int */
3342 /* change type to field type, and set to lvalue */
3344 /* an array is never an lvalue */
3345 if (!(vtop
->t
& VT_ARRAY
))
3348 } else if (tok
== '[') {
3354 } else if (tok
== '(') {
3359 if ((vtop
->t
& VT_BTYPE
) != VT_FUNC
) {
3360 /* pointer test (no array accepted) */
3361 if ((vtop
->t
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
3362 vtop
->t
= pointed_type(vtop
->t
);
3363 if ((vtop
->t
& VT_BTYPE
) != VT_FUNC
)
3367 expect("function pointer");
3370 vtop
->r
&= ~VT_LVAL
; /* no lvalue */
3372 /* get return type */
3373 s
= sym_find((unsigned)vtop
->t
>> VT_STRUCT_SHIFT
);
3374 save_regs(); /* save used temporary registers */
3377 sa
= s
->next
; /* first parameter */
3378 #ifdef INVERT_FUNC_PARAMS
3380 int *str
, len
, parlevel
, *saved_macro_ptr
;
3383 /* read each argument and store it on a stack */
3384 /* XXX: merge it with macro args ? */
3386 while (tok
!= ')') {
3390 while ((parlevel
> 0 || (tok
!= ')' && tok
!= ',')) &&
3394 else if (tok
== ')')
3396 tok_add2(&str
, &len
, tok
, &tokc
);
3399 tok_add(&str
, &len
, -1); /* end of file added */
3400 tok_add(&str
, &len
, 0);
3401 s1
= sym_push2(&args
, 0, 0, (int)str
);
3402 s1
->next
= sa
; /* add reference to argument */
3412 /* now generate code in reverse order by reading the stack */
3413 saved_macro_ptr
= macro_ptr
;
3415 macro_ptr
= (int *)args
->c
;
3419 expect("',' or ')'");
3420 gfunc_param_typed(&gf
, s
, args
->next
);
3422 free((int *)args
->c
);
3426 macro_ptr
= saved_macro_ptr
;
3431 /* compute first implicit argument if a structure is returned */
3432 if ((s
->t
& VT_BTYPE
) == VT_STRUCT
) {
3433 /* get some space for the returned structure */
3434 size
= type_size(s
->t
, &align
);
3435 loc
= (loc
- size
) & -align
;
3437 ret
.r
= VT_LOCAL
| VT_LVAL
;
3438 /* pass it as 'int' to avoid structure arg passing
3440 vset(VT_INT
, VT_LOCAL
, loc
);
3445 ret
.r
= FUNC_RET_REG
; /* return in register */
3448 #ifndef INVERT_FUNC_PARAMS
3449 while (tok
!= ')') {
3451 gfunc_param_typed(&gf
, s
, sa
);
3459 error("too few arguments to function");
3463 vsetc(ret
.t
, ret
.r
, &ret
.c
);
3476 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
3477 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
3478 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
3501 while ((l
== 0 & (tok
== '*' | tok
== '/' | tok
== '%')) |
3502 (l
== 1 & (tok
== '+' | tok
== '-')) |
3503 (l
== 2 & (tok
== TOK_SHL
| tok
== TOK_SAR
)) |
3504 (l
== 3 & ((tok
>= TOK_ULE
& tok
<= TOK_GT
) |
3505 tok
== TOK_ULT
| tok
== TOK_UGE
)) |
3506 (l
== 4 & (tok
== TOK_EQ
| tok
== TOK_NE
)) |
3507 (l
== 5 & tok
== '&') |
3508 (l
== 6 & tok
== '^') |
3509 (l
== 7 & tok
== '|') |
3510 (l
== 8 & tok
== TOK_LAND
) |
3511 (l
== 9 & tok
== TOK_LOR
)) {
3520 /* only used if non constant */
3528 if (tok
!= TOK_LAND
) {
3531 vset(VT_INT
, VT_JMPI
, t
);
3548 if (tok
!= TOK_LOR
) {
3551 vset(VT_INT
, VT_JMP
, t
);
3561 /* XXX: better constant handling */
3564 int t
, u
, c
, r1
, r2
;
3613 /* parse a constant expression and return value in vtop */
3614 void expr_const1(void)
3620 if ((vtop
->r
& (VT_VALMASK
| VT_LVAL
)) != VT_CONST
)
3625 /* parse an integer constant and return its value */
3626 int expr_const(void)
3635 /* return the label token if current token is a label, otherwise
3642 /* fast test first */
3643 if (tok
< TOK_UIDENT
)
3645 /* no need to save tokc since we expect an identifier */
3653 /* XXX: may not work in all cases (macros ?) */
3662 void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
, int case_reg
)
3667 if (tok
== TOK_IF
) {
3674 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3676 if (c
== TOK_ELSE
) {
3680 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3681 gsym(d
); /* patch else jmp */
3684 } else if (tok
== TOK_WHILE
) {
3692 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
3693 oad(0xe9, d
- ind
- 5); /* jmp */
3696 } else if (tok
== '{') {
3699 s
= local_stack
.top
;
3700 while (tok
!= '}') {
3703 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3705 /* pop locally defined symbols */
3706 sym_pop(&local_stack
, s
);
3708 } else if (tok
== TOK_RETURN
) {
3712 if ((func_vt
& VT_BTYPE
) == VT_STRUCT
) {
3713 /* if returning structure, must copy it to implicit
3714 first pointer arg location */
3715 vset(mk_pointer(func_vt
), VT_LOCAL
| VT_LVAL
, func_vc
);
3718 /* copy structure value to pointer */
3720 } else if (is_float(func_vt
)) {
3721 /* move return value to float return register */
3722 move_reg(FUNC_RET_FREG
, gv());
3724 /* move return value to standard return register */
3725 move_reg(FUNC_RET_REG
, gv());
3730 rsym
= gjmp(rsym
); /* jmp */
3731 } else if (tok
== TOK_BREAK
) {
3734 error("cannot break");
3735 *bsym
= gjmp(*bsym
);
3738 } else if (tok
== TOK_CONTINUE
) {
3741 error("cannot continue");
3742 *csym
= gjmp(*csym
);
3745 } else if (tok
== TOK_FOR
) {
3768 oad(0xe9, d
- ind
- 5); /* jmp */
3772 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
3773 oad(0xe9, c
- ind
- 5); /* jmp */
3777 if (tok
== TOK_DO
) {
3782 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
3793 if (tok
== TOK_SWITCH
) {
3801 b
= gjmp(0); /* jump to first case */
3803 block(&a
, csym
, &b
, &c
, case_reg
);
3804 /* if no default, jmp after switch */
3812 if (tok
== TOK_CASE
) {
3817 /* since a case is like a label, we must skip it with a jmp */
3820 vset(VT_INT
, case_reg
, 0);
3823 *case_sym
= gtst(1, 0);
3826 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3828 if (tok
== TOK_DEFAULT
) {
3834 error("too many 'default'");
3836 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3838 if (tok
== TOK_GOTO
) {
3840 s
= sym_find1(&label_stack
, tok
);
3841 /* put forward definition if needed */
3843 s
= sym_push1(&label_stack
, tok
, VT_FORWARD
, 0);
3844 /* label already defined */
3845 if (s
->t
& VT_FORWARD
)
3846 s
->c
= gjmp(s
->c
); /* jmp xxx */
3848 oad(0xe9, s
->c
- ind
- 5); /* jmp xxx */
3855 s
= sym_find1(&label_stack
, b
);
3857 if (!(s
->t
& VT_FORWARD
))
3858 error("multiple defined label");
3863 sym_push1(&label_stack
, b
, 0, ind
);
3865 /* we accept this, but it is a mistake */
3867 warning("deprecated use of label at end of compound statement");
3869 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3871 /* expression case */
3881 /* t is the array or struct type. c is the array or struct
3882 address. cur_index/cur_field is the pointer to the current
3883 value. 'size_only' is true if only size info is needed (only used
3885 void decl_designator(int t
, int r
, int c
,
3886 int *cur_index
, Sym
**cur_field
,
3890 int notfirst
, index
, align
, l
;
3893 if (gnu_ext
&& (l
= is_label()) != 0)
3896 while (tok
== '[' || tok
== '.') {
3898 if (!(t
& VT_ARRAY
))
3899 expect("array type");
3900 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3902 index
= expr_const();
3903 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
3904 expect("invalid index");
3908 t
= pointed_type(t
);
3909 c
+= index
* type_size(t
, &align
);
3915 if ((t
& VT_BTYPE
) != VT_STRUCT
)
3916 expect("struct/union type");
3917 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
3929 t
= f
->t
| (t
& ~VT_TYPE
);
3944 t
= pointed_type(t
);
3945 c
+= index
* type_size(t
, &align
);
3949 error("too many field init");
3950 t
= f
->t
| (t
& ~VT_TYPE
);
3954 decl_initializer(t
, r
, c
, 0, size_only
);
3958 #define EXPR_CONST 1
3961 /* store a value or an expression directly in global data or in local array */
3962 void init_putv(int t
, int r
, int c
,
3963 int v
, int expr_type
)
3965 int saved_global_expr
, bt
;
3972 /* compound literals must be allocated globally in this case */
3973 saved_global_expr
= global_expr
;
3976 global_expr
= saved_global_expr
;
3983 if ((r
& VT_VALMASK
) == VT_CONST
) {
3984 /* XXX: do casting */
3985 /* XXX: not portable */
3986 bt
= vtop
->t
& VT_BTYPE
;
3989 *(char *)c
= vtop
->c
.i
;
3992 *(short *)c
= vtop
->c
.i
;
3995 *(double *)c
= vtop
->c
.d
;
3998 *(long double *)c
= vtop
->c
.ld
;
4002 *(long long *)c
= vtop
->c
.ll
;
4006 *(int *)c
= vtop
->c
.i
;
4018 /* put zeros for variable based init */
4019 void init_putz(int t
, int r
, int c
, int size
)
4023 if ((r
& VT_VALMASK
) == VT_CONST
) {
4024 /* nothing to do because global are already set to zero */
4031 vset(VT_INT
, VT_LOCAL
, c
);
4033 vpushi((int)&memset
);
4038 /* 't' contains the type and storage info. c is the address of the
4039 object. 'first' is true if array '{' must be read (multi dimension
4040 implicit array init handling). 'size_only' is true if size only
4041 evaluation is wanted (only for arrays). */
4042 void decl_initializer(int t
, int r
, int c
, int first
, int size_only
)
4044 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
4045 int t1
, size1
, align1
, expr_type
;
4050 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
4053 t1
= pointed_type(t
);
4054 size1
= type_size(t1
, &align1
);
4057 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
4063 /* only parse strings here if correct type (otherwise: handle
4064 them as ((w)char *) expressions */
4065 if ((tok
== TOK_LSTR
&&
4066 (t1
& VT_BTYPE
) == VT_INT
) ||
4068 (t1
& VT_BTYPE
) == VT_BYTE
)) {
4069 /* XXX: move multiple string parsing in parser ? */
4070 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
4072 /* compute maximum number of chars wanted */
4074 if (n
>= 0 && nb
> (n
- array_length
))
4075 nb
= n
- array_length
;
4078 warning("initializer-string for array is too long");
4080 init_putv(t1
, r
, c
+ (array_length
+ i
) * size1
,
4081 ts
->str
[i
], EXPR_VAL
);
4087 /* only add trailing zero if enough storage (no
4088 warning in this case since it is standard) */
4089 if (n
< 0 || array_length
< n
) {
4091 init_putv(t1
, r
, c
+ (array_length
* size1
), 0, EXPR_VAL
);
4097 while (tok
!= '}') {
4098 decl_designator(t
, r
, c
, &index
, NULL
, size_only
);
4099 if (n
>= 0 && index
>= n
)
4100 error("index too large");
4101 /* must put zero in holes (note that doing it that way
4102 ensures that it even works with designators) */
4103 if (!size_only
&& array_length
< index
) {
4104 init_putz(t1
, r
, c
+ array_length
* size1
,
4105 (index
- array_length
) * size1
);
4108 if (index
> array_length
)
4109 array_length
= index
;
4110 /* special test for multi dimensional arrays (may not
4111 be strictly correct if designators are used at the
4113 if (index
>= n
&& no_oblock
)
4122 /* put zeros at the end */
4123 if (!size_only
&& n
>= 0 && array_length
< n
) {
4124 init_putz(t1
, r
, c
+ array_length
* size1
,
4125 (n
- array_length
) * size1
);
4127 /* patch type size if needed */
4129 s
->c
= array_length
;
4130 } else if ((t
& VT_BTYPE
) == VT_STRUCT
&& tok
== '{') {
4131 /* XXX: union needs only one init */
4133 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
4138 while (tok
!= '}') {
4139 decl_designator(t
, r
, c
, NULL
, &f
, size_only
);
4140 /* fill with zero between fields */
4142 if (!size_only
&& array_length
< index
) {
4143 init_putz(t
, r
, c
+ array_length
,
4144 index
- array_length
);
4146 index
= index
+ type_size(f
->t
, &align1
);
4147 if (index
> array_length
)
4148 array_length
= index
;
4154 /* put zeros at the end */
4155 if (!size_only
&& array_length
< n
) {
4156 init_putz(t
, r
, c
+ array_length
,
4160 } else if (tok
== '{') {
4162 decl_initializer(t
, r
, c
, first
, size_only
);
4164 } else if (size_only
) {
4165 /* just skip expression */
4167 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
4171 else if (tok
== ')')
4176 /* currently, we always use constant expression for globals
4177 (may change for scripting case) */
4178 expr_type
= EXPR_CONST
;
4179 if ((r
& VT_VALMASK
) == VT_LOCAL
)
4180 expr_type
= EXPR_ANY
;
4181 init_putv(t
, r
, c
, 0, expr_type
);
4185 /* parse an initializer for type 't' if 'has_init' is true, and
4186 allocate space in local or global data space ('r' is either
4187 VT_LOCAL or VT_CONST). The allocated address in returned */
4188 int decl_initializer_alloc(int t
, int r
, int has_init
)
4190 int size
, align
, addr
, tok1
;
4191 int *init_str
, init_len
, level
, *saved_macro_ptr
;
4193 size
= type_size(t
, &align
);
4194 /* If unknown size, we must evaluate it before
4195 evaluating initializers because
4196 initializers can generate global data too
4197 (e.g. string pointers or ISOC99 compound
4198 literals). It also simplifies local
4199 initializers handling */
4202 saved_macro_ptr
= NULL
; /* avoid warning */
4206 error("unknown type size");
4207 /* get all init string */
4209 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
4211 error("unexpected end of file in initializer");
4212 tok_add2(&init_str
, &init_len
, tok
, &tokc
);
4215 else if (tok
== '}') {
4223 tok_add(&init_str
, &init_len
, -1);
4224 tok_add(&init_str
, &init_len
, 0);
4227 saved_macro_ptr
= macro_ptr
;
4228 macro_ptr
= init_str
;
4230 decl_initializer(t
, r
, 0, 1, 1);
4231 /* prepare second initializer parsing */
4232 macro_ptr
= init_str
;
4235 /* if still unknown size, error */
4236 size
= type_size(t
, &align
);
4238 error("unknown type size");
4240 if ((r
& VT_VALMASK
) == VT_LOCAL
) {
4241 loc
= (loc
- size
) & -align
;
4244 glo
= (glo
+ align
- 1) & -align
;
4246 /* very important to increment global
4247 pointer at this time because
4248 initializers themselves can create new
4253 decl_initializer(t
, r
, addr
, 1, 0);
4254 /* restore parse state if needed */
4257 macro_ptr
= saved_macro_ptr
;
4265 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
4268 int *a
, t
, b
, v
, addr
, has_init
, size
, align
, r
, u
;
4272 if (!parse_btype(&b
)) {
4273 /* skip redundant ';' */
4274 /* XXX: find more elegant solution */
4279 /* special test for old K&R protos without explicit int
4280 type. Only accepted when defining global data */
4281 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
4285 if (((b
& VT_BTYPE
) == VT_ENUM
||
4286 (b
& VT_BTYPE
) == VT_STRUCT
) &&
4288 /* we accept no variable after */
4292 while (1) { /* iterate thru each declaration */
4293 t
= type_decl(&v
, b
, TYPE_DIRECT
);
4297 type_to_str(buf
, sizeof(buf
), t
, get_tok_str(v
, NULL
));
4298 printf("type = '%s'\n", buf
);
4303 error("cannot use local functions");
4305 expect("function definition");
4306 /* patch forward references */
4307 if ((sym
= sym_find(v
)) && (sym
->r
& VT_FORWARD
)) {
4308 greloc_patch(sym
, ind
);
4311 /* put function address */
4312 sym
= sym_push1(&global_stack
, v
, t
, ind
);
4315 funcname
= get_tok_str(v
, NULL
);
4316 /* push a dummy symbol to enable local sym storage */
4317 sym_push1(&local_stack
, 0, 0, 0);
4318 /* define parameters */
4319 sym
= sym_find((unsigned)t
>> VT_STRUCT_SHIFT
);
4320 /* XXX: the following is x86 dependant -> move it to
4323 /* if the function returns a structure, then add an
4324 implicit pointer parameter */
4326 if ((func_vt
& VT_BTYPE
) == VT_STRUCT
) {
4330 while (sym
= sym
->next
) {
4332 sym_push(sym
->v
& ~SYM_FIELD
, u
,
4333 VT_LOCAL
| VT_LVAL
, addr
);
4334 size
= type_size(u
, &align
);
4335 size
= (size
+ 3) & ~3;
4336 #ifdef FUNC_STRUCT_PARAM_AS_PTR
4337 /* structs are passed as pointer */
4338 if ((u
& VT_BTYPE
) == VT_STRUCT
) {
4345 o(0xe58955); /* push %ebp, mov %esp, %ebp */
4346 a
= (int *)oad(0xec81, 0); /* sub $xxx, %esp */
4348 block(NULL
, NULL
, NULL
, NULL
, 0);
4350 o(0xc3c9); /* leave, ret */
4351 *a
= (-loc
+ 3) & -4; /* align local size to word &
4352 save local variables */
4353 sym_pop(&label_stack
, NULL
); /* reset label stack */
4354 sym_pop(&local_stack
, NULL
); /* reset local stack */
4355 funcname
= ""; /* for safety */
4356 func_vt
= VT_VOID
; /* for safety */
4359 if (b
& VT_TYPEDEF
) {
4360 /* save typedefed type */
4361 /* XXX: test storage specifiers ? */
4362 sym_push(v
, t
| VT_TYPEDEF
, 0, 0);
4363 } else if ((t
& VT_BTYPE
) == VT_FUNC
) {
4364 /* external function definition */
4365 external_sym(v
, t
, 0);
4367 /* not lvalue if array */
4369 if (!(t
& VT_ARRAY
))
4371 if (b
& VT_EXTERN
) {
4372 /* external variable */
4373 external_sym(v
, t
, r
);
4379 has_init
= (tok
== '=');
4382 addr
= decl_initializer_alloc(t
, r
,
4384 if (l
== VT_CONST
) {
4385 /* global scope: see if already defined */
4389 if (!is_compatible_types(sym
->t
, t
))
4390 error("incompatible types for redefinition of '%s'",
4391 get_tok_str(v
, NULL
));
4392 if (!(sym
->r
& VT_FORWARD
))
4393 error("redefinition of '%s'", get_tok_str(v
, NULL
));
4394 greloc_patch(sym
, addr
);
4397 sym_push(v
, t
, r
, addr
);
4411 /* put all global symbols in the extern stack and do all the
4412 resolving which can be done without using external symbols from DLLs */
4413 /* XXX: could try to verify types, but would not to save them in
4415 void resolve_global_syms(void)
4417 Sym
*s
, *s1
, *ext_sym
;
4420 s
= global_stack
.top
;
4423 /* do not save static or typedefed symbols or types */
4424 if (!(s
->t
& (VT_STATIC
| VT_TYPEDEF
)) &&
4425 !(s
->v
& (SYM_FIELD
| SYM_STRUCT
)) &&
4426 (s
->v
< SYM_FIRST_ANOM
)) {
4427 ext_sym
= sym_find1(&extern_stack
, s
->v
);
4429 /* if the symbol do not exist, we simply save it */
4430 ext_sym
= sym_push1(&extern_stack
, s
->v
, s
->t
, s
->c
);
4432 } else if (ext_sym
->r
& VT_FORWARD
) {
4433 /* external symbol already exists, but only as forward
4435 if (!(s
->r
& VT_FORWARD
)) {
4436 /* s is not forward, so we can relocate all symbols */
4437 greloc_patch(ext_sym
, s
->c
);
4439 /* the two symbols are forward: merge them */
4440 p
= (Reloc
**)&ext_sym
->c
;
4446 /* external symbol already exists and is defined :
4447 patch all references to it */
4448 if (!(s
->r
& VT_FORWARD
))
4449 error("'%s' defined twice", get_tok_str(s
->v
, NULL
));
4450 greloc_patch(s
, ext_sym
->c
);
4457 /* compile a C file. Return non zero if errors. */
4458 int tcc_compile_file(const char *filename1
)
4462 filename
= (char *)filename1
;
4466 file
= fopen(filename
, "r");
4468 error("file '%s' not found", filename
);
4469 include_stack_ptr
= include_stack
;
4470 ifdef_stack_ptr
= ifdef_stack
;
4473 anon_sym
= SYM_FIRST_ANOM
;
4475 define_start
= define_stack
.top
;
4477 ch
= '\n'; /* needed to parse correctly first preprocessor command */
4481 expect("declaration");
4484 /* reset define stack, but leave -Dsymbols (may be incorrect if
4485 they are undefined) */
4486 sym_pop(&define_stack
, define_start
);
4488 resolve_global_syms();
4490 sym_pop(&global_stack
, NULL
);
4495 /* open a dynamic library so that its symbol are available for
4496 compiled programs */
4497 void open_dll(char *libname
)
4502 snprintf(buf
, sizeof(buf
), "lib%s.so", libname
);
4503 h
= dlopen(buf
, RTLD_GLOBAL
| RTLD_LAZY
);
4505 error((char *)dlerror());
4508 void resolve_extern_syms(void)
4514 s
= extern_stack
.top
;
4517 if (s
->r
& VT_FORWARD
) {
4518 /* if there is at least one relocation to do, then find it
4521 str
= get_tok_str(s
->v
, NULL
);
4522 addr
= (int)dlsym(NULL
, str
);
4524 error("unresolved external reference '%s'", str
);
4525 greloc_patch(s
, addr
);
4532 /* output a binary file (for testing) */
4533 void build_exe(char *filename
)
4536 f
= fopen(filename
, "w");
4537 fwrite((void *)prog
, 1, ind
- prog
, f
);
4541 int main(int argc
, char **argv
)
4545 char *p
, *r
, *outfile
;
4548 include_paths
[0] = "/usr/include";
4549 include_paths
[1] = "/usr/lib/tcc";
4550 include_paths
[2] = "/usr/local/lib/tcc";
4551 nb_include_paths
= 3;
4553 /* add all tokens */
4554 tok_ident
= TOK_IDENT
;
4555 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";
4559 tok_alloc(p
, r
- p
- 1);
4563 /* standard defines */
4564 define_symbol("__STDC__");
4566 define_symbol("__i386__");
4568 /* tiny C specific defines */
4569 define_symbol("__TINYC__");
4571 glo
= (int)malloc(DATA_SIZE
);
4572 memset((void *)glo
, 0, DATA_SIZE
);
4573 prog
= (int)malloc(TEXT_SIZE
);
4579 if (optind
>= argc
) {
4581 printf("tcc version 0.9.2 - Tiny C Compiler - Copyright (C) 2001 Fabrice Bellard\n"
4582 "usage: tcc [-Idir] [-Dsym] [-llib] [-i infile] infile [infile_args...]\n");
4590 if (nb_include_paths
>= INCLUDE_PATHS_MAX
)
4591 error("too many include paths");
4592 include_paths
[nb_include_paths
++] = r
+ 2;
4593 } else if (r
[1] == 'D') {
4594 define_symbol(r
+ 2);
4595 } else if (r
[1] == 'l') {
4597 } else if (r
[1] == 'i') {
4600 tcc_compile_file(argv
[optind
++]);
4601 } else if (r
[1] == 'o') {
4602 /* currently, only for testing, so not documented */
4605 outfile
= argv
[optind
++];
4607 fprintf(stderr
, "invalid option -- '%s'\n", r
);
4612 tcc_compile_file(argv
[optind
]);
4614 resolve_extern_syms();
4620 s
= sym_find1(&extern_stack
, TOK_MAIN
);
4621 if (!s
|| (s
->r
& VT_FORWARD
))
4622 error("main() not defined");
4623 t
= (int (*)())s
->c
;
4624 return (*t
)(argc
- optind
, argv
+ optind
);