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.
23 #ifndef CONFIG_TCC_STATIC
28 /* preprocessor debug */
31 /* these sizes are dummy for unix, because malloc() does not use
32 memory when the pages are not used */
33 #define TEXT_SIZE (4*1024*1024)
34 #define DATA_SIZE (4*1024*1024)
36 #define INCLUDE_STACK_SIZE 32
37 #define IFDEF_STACK_SIZE 64
38 #define VSTACK_SIZE 64
39 #define STRING_MAX_SIZE 1024
40 #define INCLUDE_PATHS_MAX 32
42 #define TOK_HASH_SIZE 521
43 #define TOK_ALLOC_INCR 256 /* must be a power of two */
44 #define SYM_HASH_SIZE 263
46 /* number of available temporary registers */
48 /* return register for functions */
49 #define FUNC_RET_REG 0
50 /* defined if function parameters must be evaluated in reverse order */
51 #define INVERT_FUNC_PARAMS
52 /* defined if structures are passed as pointers. Otherwise structures
53 are directly pushed on stack. */
54 //#define FUNC_STRUCT_PARAM_AS_PTR
56 /* token symbol management */
57 typedef struct TokenSym
{
58 struct TokenSym
*hash_next
;
59 int tok
; /* token number */
64 /* symbol management */
66 int v
; /* symbol token */
67 int t
; /* associated type */
68 int c
; /* associated number */
69 struct Sym
*next
; /* next related symbol */
70 struct Sym
*prev
; /* prev symbol in stack */
71 struct Sym
*hash_next
; /* next symbol in hash table */
74 typedef struct SymStack
{
76 struct Sym
*hash
[SYM_HASH_SIZE
];
79 /* relocation entry (currently only used for functions or variables */
80 typedef struct Reloc
{
81 int type
; /* type of relocation */
82 int addr
; /* address of relocation */
83 struct Reloc
*next
; /* next relocation */
86 #define RELOC_ADDR32 1 /* 32 bits relocation */
87 #define RELOC_REL32 2 /* 32 bits relative relocation */
90 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
91 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
92 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
94 #define FUNC_NEW 1 /* ansi function prototype */
95 #define FUNC_OLD 2 /* old function prototype */
96 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
98 /* field 'Sym.t' for macros */
99 #define MACRO_OBJ 0 /* object like macro */
100 #define MACRO_FUNC 1 /* function like macro */
102 /* type_decl() types */
103 #define TYPE_ABSTRACT 1 /* type without variable */
104 #define TYPE_DIRECT 2 /* type with variable */
114 int ch
, ch1
, tok
, tokc
, tok1
, tok1c
;
116 /* loc : local variable index
117 glo : global variable index
118 ind : output code ptr
121 anon_sym: anonymous symbol index
124 prog
, ind
, loc
, glo
, vt
, vc
, const_wanted
, line_num
;
125 int global_expr
; /* true if compound literals must be allocated
126 globally (used during initializers parsing */
127 int func_vt
, func_vc
; /* current function return type (used by
128 return instruction) */
130 TokenSym
**table_ident
;
131 TokenSym
*hash_ident
[TOK_HASH_SIZE
];
132 char token_buf
[STRING_MAX_SIZE
+ 1];
133 char *filename
, *funcname
;
134 /* contains global symbols which remain between each translation unit */
135 SymStack extern_stack
;
136 SymStack define_stack
, global_stack
, local_stack
, label_stack
;
138 int vstack
[VSTACK_SIZE
], *vstack_ptr
;
139 int *macro_ptr
, *macro_ptr_allocated
;
140 IncludeFile include_stack
[INCLUDE_STACK_SIZE
], *include_stack_ptr
;
141 int ifdef_stack
[IFDEF_STACK_SIZE
], *ifdef_stack_ptr
;
142 char *include_paths
[INCLUDE_PATHS_MAX
];
143 int nb_include_paths
;
145 /* use GNU C extensions */
148 /* The current value can be: */
149 #define VT_VALMASK 0x000f
150 #define VT_CONST 0x000a /* constant in vc
151 (must be first non register value) */
152 #define VT_LLOCAL 0x000b /* lvalue, offset on stack */
153 #define VT_LOCAL 0x000c /* offset on stack */
154 #define VT_CMP 0x000d /* the value is stored in processor flags (in vc) */
155 #define VT_JMP 0x000e /* value is the consequence of jmp true */
156 #define VT_JMPI 0x000f /* value is the consequence of jmp false */
157 #define VT_LVAL 0x0010 /* var is an lvalue */
158 #define VT_LVALN -17 /* ~VT_LVAL */
159 #define VT_FORWARD 0x0020 /* value is forward reference
160 (only used for functions) */
164 #define VT_VOID 0x00040
165 #define VT_BYTE 0x00080 /* signed byte type */
166 #define VT_PTR 0x00100 /* pointer increment */
167 #define VT_UNSIGNED 0x00200 /* unsigned type */
168 #define VT_ARRAY 0x00400 /* array type (only used in parsing) */
169 #define VT_ENUM 0x00800 /* enum definition */
170 #define VT_FUNC 0x01000 /* function type */
171 #define VT_STRUCT 0x002000 /* struct/union definition */
172 #define VT_SHORT 0x004000 /* short type */
173 #define VT_STRUCT_SHIFT 18 /* structure/enum name shift (14 bits left) */
175 #define VT_TYPE 0xfffc7fc0 /* type mask */
178 #define VT_EXTERN 0x00008000 /* extern definition */
179 #define VT_STATIC 0x00010000 /* static variable */
180 #define VT_TYPEDEF 0x00020000 /* typedef definition */
185 /* warning: the following compare tokens depend on i386 asm code */
197 #define TOK_LAND 0xa0
201 #define TOK_MID 0xa3 /* inc/dec, to void constant */
203 #define TOK_ARROW 0xa7
204 #define TOK_DOTS 0xa8 /* three dots */
205 #define TOK_SHR 0xa9 /* unsigned shift right */
206 #define TOK_UDIV 0xb0 /* unsigned division */
207 #define TOK_UMOD 0xb1 /* unsigned modulo */
208 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
209 #define TOK_NUM 0xb3 /* number in tokc */
210 #define TOK_CCHAR 0xb4 /* char constant in tokc */
211 #define TOK_STR 0xb5 /* pointer to string in tokc */
212 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
213 #define TOK_LCHAR 0xb7
214 #define TOK_LSTR 0xb8
216 #define TOK_SHL 0x01 /* shift left */
217 #define TOK_SAR 0x02 /* signed shift right */
219 /* assignement operators : normal operator or 0x80 */
220 #define TOK_A_MOD 0xa5
221 #define TOK_A_AND 0xa6
222 #define TOK_A_MUL 0xaa
223 #define TOK_A_ADD 0xab
224 #define TOK_A_SUB 0xad
225 #define TOK_A_DIV 0xaf
226 #define TOK_A_XOR 0xde
227 #define TOK_A_OR 0xfc
228 #define TOK_A_SHL 0x81
229 #define TOK_A_SAR 0x82
231 /* all identificators and strings have token above that */
232 #define TOK_IDENT 256
253 /* ignored types Must have contiguous values */
263 /* unsupported type */
275 /* preprocessor only */
276 TOK_UIDENT
, /* first "user" ident (not keyword) */
277 TOK_DEFINE
= TOK_UIDENT
,
293 /* special identifiers */
305 void decl_initializer(int t
, int c
, int first
, int size_only
);
306 int decl_initializer_alloc(int t
, int has_init
);
312 void macro_subst(int **tok_str
, int *tok_len
,
313 Sym
**nested_list
, int *macro_str
);
314 int save_reg_forced(int r
);
316 int type_size(int t
, int *a
);
317 int pointed_type(int t
);
318 int pointed_size(int t
);
320 int type_decl(int *v
, int t
, int td
);
322 #ifdef CONFIG_TCC_STATIC
324 #define RTLD_LAZY 0x001
325 #define RTLD_NOW 0x002
326 #define RTLD_GLOBAL 0x100
328 /* dummy function for profiling */
329 void *dlopen(const char *filename
, int flag
)
334 const char *dlerror(void)
339 typedef struct TCCSyms
{
344 #define TCCSYM(a) { #a, &a, },
346 /* add the symbol you want here if no dynamic linking is done */
347 static TCCSyms tcc_syms
[] = {
355 void *dlsym(void *handle
, char *symbol
)
359 while (p
->str
!= NULL
) {
360 if (!strcmp(p
->str
, symbol
))
371 return (c
>= 'a' && c
<= 'z') ||
372 (c
>= 'A' && c
<= 'Z') ||
378 return c
>= '0' & c
<= '9';
384 for(f
= include_stack
; f
< include_stack_ptr
; f
++)
385 fprintf(stderr
, "In file included from %s:%d:\n",
386 f
->filename
, f
->line_num
);
387 fprintf(stderr
, "%s:%d: ", filename
, line_num
);
390 void error(const char *fmt
, ...)
395 vfprintf(stderr
, fmt
, ap
);
396 fprintf(stderr
, "\n");
401 void expect(const char *msg
)
403 error("%s expected", msg
);
406 void warning(const char *msg
)
409 fprintf(stderr
, "warning: %s\n", msg
);
415 error("'%c' expected", c
);
425 TokenSym
*tok_alloc(char *str
, int len
)
427 TokenSym
*ts
, **pts
, **ptable
;
434 h
= ((h
<< 8) | (str
[i
] & 0xff)) % TOK_HASH_SIZE
;
436 pts
= &hash_ident
[h
];
441 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
443 pts
= &(ts
->hash_next
);
445 /* expand token table if needed */
446 i
= tok_ident
- TOK_IDENT
;
447 if ((i
% TOK_ALLOC_INCR
) == 0) {
448 ptable
= realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
450 error("memory full");
451 table_ident
= ptable
;
453 ts
= malloc(sizeof(TokenSym
) + len
);
454 if (!ts
|| tok_ident
>= SYM_FIRST_ANOM
)
455 error("memory full");
457 ts
->tok
= tok_ident
++;
459 ts
->hash_next
= NULL
;
460 memcpy(ts
->str
, str
, len
+ 1);
465 void add_char(char **pp
, int c
)
469 if (c
== '\'' || c
== '\"' || c
== '\\') {
470 /* XXX: could be more precise if char or string */
473 if (c
>= 32 && c
<= 126) {
480 *p
++ = '0' + ((c
>> 6) & 7);
481 *p
++ = '0' + ((c
>> 3) & 7);
482 *p
++ = '0' + (c
& 7);
488 /* XXX: buffer overflow */
489 char *get_tok_str(int v
, int c
)
491 static char buf
[STRING_MAX_SIZE
+ 1];
497 sprintf(buf
, "%d", c
);
499 } else if (v
== TOK_CCHAR
|| v
== TOK_LCHAR
) {
506 } else if (v
== TOK_STR
|| v
== TOK_LSTR
) {
510 for(i
=0;i
<ts
->len
;i
++)
511 add_char(&p
, ts
->str
[i
]);
515 } else if (v
< TOK_IDENT
) {
520 } else if (v
< tok_ident
) {
521 return table_ident
[v
- TOK_IDENT
]->str
;
523 /* should never happen */
528 /* push, without hashing */
529 Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
532 s
= malloc(sizeof(Sym
));
534 error("memory full");
545 /* find a symbol and return its associated structure. 's' is the top
546 of the symbol stack */
547 Sym
*sym_find2(Sym
*s
, int v
)
557 /* find a symbol and return its associated structure. 'st' is the
559 Sym
*sym_find1(SymStack
*st
, int v
)
563 s
= st
->hash
[v
% SYM_HASH_SIZE
];
572 Sym
*sym_push1(SymStack
*st
, int v
, int t
, int c
)
575 s
= sym_push2(&st
->top
, v
, t
, c
);
576 /* add in hash table */
577 ps
= &st
->hash
[s
->v
% SYM_HASH_SIZE
];
583 /* find a symbol in the right symbol space */
587 s
= sym_find1(&local_stack
, v
);
589 s
= sym_find1(&global_stack
, v
);
593 /* push a given symbol on the symbol stack */
594 Sym
*sym_push(int v
, int t
, int c
)
597 return sym_push1(&local_stack
, v
, t
, c
);
599 return sym_push1(&global_stack
, v
, t
, c
);
602 /* pop symbols until top reaches 'b' */
603 void sym_pop(SymStack
*st
, Sym
*b
)
610 /* free hash table entry */
611 st
->hash
[s
->v
% SYM_HASH_SIZE
] = s
->hash_next
;
618 /* undefined a hashed symbol (used for #undef). Its name is set to
620 void sym_undef(SymStack
*st
, Sym
*s
)
623 ss
= &st
->hash
[s
->v
% SYM_HASH_SIZE
];
624 while (*ss
!= NULL
) {
627 ss
= &(*ss
)->hash_next
;
633 /* no need to put that inline */
636 if (include_stack_ptr
== include_stack
)
638 /* pop include stack */
642 file
= include_stack_ptr
->file
;
643 filename
= include_stack_ptr
->filename
;
644 line_num
= include_stack_ptr
->line_num
;
648 /* read next char from current input file */
649 static inline void inp(void)
652 /* faster than fgetc */
653 ch1
= getc_unlocked(file
);
655 if (handle_eof() < 0)
662 // printf("ch1=%c 0x%x\n", ch1, ch1);
665 /* input with '\\n' handling */
666 static inline void minp(void)
671 if (ch
== '\\' && ch1
== '\n') {
675 //printf("ch=%c 0x%x\n", ch, ch);
679 /* same as minp, but also skip comments */
687 /* single line C++ comments */
689 while (ch1
!= '\n' && ch1
!= -1)
692 ch
= ' '; /* return space */
693 } else if (ch1
== '*') {
699 if (c
== '*' && ch1
== '/') {
701 ch
= ' '; /* return space */
713 void skip_spaces(void)
715 while (ch
== ' ' || ch
== '\t')
719 /* skip block of text until #else, #elif or #endif. skip also pairs of
721 void preprocess_skip()
737 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
739 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
741 else if (tok
== TOK_ENDIF
)
747 inline int is_long_tok(int t
)
749 return (t
== TOK_NUM
||
750 t
== TOK_CCHAR
|| t
== TOK_LCHAR
||
751 t
== TOK_STR
|| t
== TOK_LSTR
);
754 void tok_add(int **tok_str
, int *tok_len
, int t
)
759 if ((len
& 63) == 0) {
760 str
= realloc(str
, (len
+ 64) * sizeof(int));
769 void tok_add2(int **tok_str
, int *tok_len
, int t
, int c
)
771 tok_add(tok_str
, tok_len
, t
);
773 tok_add(tok_str
, tok_len
, c
);
776 /* eval an expression for #if/#elif */
777 int expr_preprocess()
787 next(); /* do macro subst */
788 if (tok
== TOK_DEFINED
) {
793 c
= sym_find1(&define_stack
, tok
) != 0;
798 } else if (tok
>= TOK_IDENT
) {
799 /* if undefined macro */
803 tok_add2(&str
, &len
, tok
, tokc
);
805 tok_add(&str
, &len
, -1); /* simulate end of file */
806 tok_add(&str
, &len
, 0);
807 /* now evaluate C constant expression */
817 void tok_print(int *str
)
828 printf(" %s", get_tok_str(t
, c
));
834 /* XXX: should be more factorized */
835 void define_symbol(char *sym
)
840 ts
= tok_alloc(sym
, 0);
843 tok_add2(&str
, &len
, TOK_NUM
, 1);
844 tok_add(&str
, &len
, 0);
845 sym_push1(&define_stack
, ts
->tok
, MACRO_OBJ
, (int)str
);
850 int size
, i
, c
, v
, t
, *str
, len
;
851 char buf
[1024], *q
, *p
;
854 Sym
**ps
, *first
, *s
;
859 if (tok
== TOK_DEFINE
) {
862 /* XXX: should check if same macro (ANSI) */
865 /* '(' must be just after macro definition for MACRO_FUNC */
872 tok
= TOK___VA_ARGS__
;
873 s
= sym_push1(&define_stack
, tok
| SYM_FIELD
, 0, 0);
887 if (ch
== '\n' || ch
== -1)
890 tok_add2(&str
, &len
, tok
, tokc
);
892 tok_add(&str
, &len
, 0);
894 printf("define %s %d: ", get_tok_str(v
, 0), t
);
897 s
= sym_push1(&define_stack
, v
, t
, (int)str
);
899 } else if (tok
== TOK_UNDEF
) {
901 s
= sym_find1(&define_stack
, tok
);
902 /* undefine symbol by putting an invalid name */
904 sym_undef(&define_stack
, s
);
905 } else if (tok
== TOK_INCLUDE
) {
910 } else if (ch
== '\"') {
915 while (ch
!= c
&& ch
!= '\n' && ch
!= -1) {
916 if ((q
- buf
) < sizeof(buf
) - 1)
924 error("#include syntax error");
925 /* XXX: buffer overflow */
926 strcpy(buf
, get_tok_str(tok
, tokc
));
929 if (include_stack_ptr
>= include_stack
+ INCLUDE_STACK_SIZE
)
930 error("memory full");
932 /* first search in current dir if "header.h" */
933 /* XXX: buffer overflow */
935 p
= strrchr(filename
, '/');
937 size
= p
+ 1 - filename
;
938 memcpy(buf1
, filename
, size
);
941 f
= fopen(buf1
, "r");
945 /* now search in standard include path */
946 for(i
=nb_include_paths
- 1;i
>=0;i
--) {
947 strcpy(buf1
, include_paths
[i
]);
950 f
= fopen(buf1
, "r");
954 error("include file '%s' not found", buf1
);
957 /* push current file in stack */
958 /* XXX: fix current line init */
959 include_stack_ptr
->file
= file
;
960 include_stack_ptr
->filename
= filename
;
961 include_stack_ptr
->line_num
= line_num
;
964 filename
= strdup(buf1
);
966 } else if (tok
== TOK_IFNDEF
) {
969 } else if (tok
== TOK_IF
) {
970 c
= expr_preprocess();
972 } else if (tok
== TOK_IFDEF
) {
976 c
= (sym_find1(&define_stack
, tok
) != 0) ^ c
;
978 if (ifdef_stack_ptr
>= ifdef_stack
+ IFDEF_STACK_SIZE
)
979 error("memory full");
980 *ifdef_stack_ptr
++ = c
;
982 } else if (tok
== TOK_ELSE
) {
983 if (ifdef_stack_ptr
== ifdef_stack
||
984 (ifdef_stack_ptr
[-1] & 2))
985 error("#else after #else");
986 c
= (ifdef_stack_ptr
[-1] ^= 3);
988 } else if (tok
== TOK_ELIF
) {
989 if (ifdef_stack_ptr
== ifdef_stack
||
990 ifdef_stack_ptr
[-1] > 1)
991 error("#elif after #else");
992 c
= expr_preprocess();
993 ifdef_stack_ptr
[-1] = c
;
999 } else if (tok
== TOK_ENDIF
) {
1000 if (ifdef_stack_ptr
== ifdef_stack
)
1003 } else if (tok
== TOK_LINE
) {
1013 /* XXX: potential memory leak */
1014 filename
= strdup(get_tok_str(tok
, tokc
));
1016 } else if (tok
== TOK_ERROR
) {
1019 /* ignore other preprocess commands or #! for C scripts */
1020 while (ch
!= '\n' && ch
!= -1)
1024 /* read a number in base b */
1030 if (ch
>= 'a' & ch
<= 'f')
1032 else if (ch
>= 'A' & ch
<= 'F')
1046 /* read a character for string or char constant and eval escape codes */
1055 /* at most three octal digits */
1059 c
= c
* 8 + ch
- '0';
1062 c
= c
* 8 + ch
- '0';
1067 } else if (ch
== 'x') {
1093 /* return next token without macro substitution */
1094 void next_nomacro1()
1102 while (ch
== '\n') {
1104 while (ch
== ' ' || ch
== 9)
1107 /* preprocessor command if # at start of line after
1112 if (ch
!= ' ' && ch
!= '\t' && ch
!= '\f')
1130 while (isid(ch
) | isnum(ch
)) {
1131 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1132 error("ident too long");
1137 ts
= tok_alloc(token_buf
, q
- token_buf
);
1139 } else if (isnum(ch
)) {
1145 if (ch
== 'x' || ch
== 'X') {
1148 } else if (ch
== 'b' || ch
== 'B') {
1154 /* XXX: add unsigned constant support (ANSI) */
1155 while (ch
== 'L' || ch
== 'l' || ch
== 'U' || ch
== 'u')
1158 } else if (ch
== '\'') {
1166 } else if (ch
== '\"') {
1171 while (ch
!= '\"') {
1174 error("unterminated string");
1175 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1176 error("string too long");
1180 tokc
= (int)tok_alloc(token_buf
, q
- token_buf
);
1183 q
= "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\247..\250##\266";
1188 if (*q
== tok
& q
[1] == ch
) {
1191 /* three chars tests */
1192 if (tok
== TOK_SHL
| tok
== TOK_SAR
) {
1197 } else if (tok
== TOK_DOTS
) {
1199 error("parse error");
1206 /* single char substitutions */
1209 else if (tok
== '>')
1214 /* return next token without macro substitution. Can read input from
1222 if (is_long_tok(tok
))
1223 tokc
= *macro_ptr
++;
1230 /* substitute args in macro_str and return allocated string */
1231 int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
1233 int *st
, last_tok
, t
, c
, notfirst
, *str
, len
;
1249 s
= sym_find2(args
, t
);
1251 token_buf
[0] = '\0';
1253 /* XXX: buffer overflow */
1257 strcat(token_buf
, " ");
1262 strcat(token_buf
, get_tok_str(t
, c
));
1266 printf("stringize: %s\n", token_buf
);
1269 ts
= tok_alloc(token_buf
, 0);
1270 tok_add2(&str
, &len
, TOK_STR
, (int)ts
);
1272 tok_add(&str
, &len
, t
);
1274 } else if (is_long_tok(t
)) {
1275 tok_add2(&str
, &len
, t
, *macro_str
++);
1277 s
= sym_find2(args
, t
);
1280 /* if '##' is present before or after , no arg substitution */
1281 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
1283 tok_add(&str
, &len
, *st
++);
1285 macro_subst(&str
, &len
, nested_list
, st
);
1288 tok_add(&str
, &len
, t
);
1293 tok_add(&str
, &len
, 0);
1297 /* handle the '##' operator */
1298 int *macro_twosharps(int *macro_str
)
1301 int *macro_str1
, macro_str1_len
, *macro_ptr1
;
1312 if (*macro_ptr
== TOK_TWOSHARPS
) {
1314 macro_ptr1
= macro_ptr
;
1321 /* XXX: we handle only most common cases:
1322 ident + ident or ident + number */
1323 if (tok
>= TOK_IDENT
&&
1324 (t
>= TOK_IDENT
|| t
== TOK_NUM
)) {
1325 /* XXX: buffer overflow */
1326 p
= get_tok_str(tok
, tokc
);
1327 strcpy(token_buf
, p
);
1328 p
= get_tok_str(t
, c
);
1329 strcat(token_buf
, p
);
1330 ts
= tok_alloc(token_buf
, 0);
1331 tok_add2(¯o_str1
, ¯o_str1_len
, ts
->tok
, 0);
1333 /* cannot merge tokens: skip '##' */
1334 macro_ptr
= macro_ptr1
;
1338 tok_add2(¯o_str1
, ¯o_str1_len
, tok
, tokc
);
1341 tok_add(¯o_str1
, ¯o_str1_len
, 0);
1347 /* do macro substitution of macro_str and add result to
1348 (tok_str,tok_len). If macro_str is NULL, then input stream token is
1349 substituted. 'nested_list' is the list of all macros we got inside
1350 to avoid recursing. */
1351 void macro_subst(int **tok_str
, int *tok_len
,
1352 Sym
**nested_list
, int *macro_str
)
1354 Sym
*s
, *args
, *sa
, *sa1
;
1355 int *str
, parlevel
, len
, *mstr
, t
, *saved_macro_ptr
;
1356 int mstr_allocated
, *macro_str1
;
1358 saved_macro_ptr
= macro_ptr
;
1359 macro_ptr
= macro_str
;
1362 /* first scan for '##' operator handling */
1363 macro_str1
= macro_twosharps(macro_str
);
1364 macro_ptr
= macro_str1
;
1371 /* special macros */
1372 if (tok
== TOK___LINE__
) {
1373 tok_add2(tok_str
, tok_len
, TOK_NUM
, line_num
);
1374 } else if (tok
== TOK___FILE__
) {
1375 tok_add2(tok_str
, tok_len
, TOK_STR
,
1376 (int)tok_alloc(filename
, 0));
1377 } else if (tok
== TOK___DATE__
) {
1378 tok_add2(tok_str
, tok_len
, TOK_STR
,
1379 (int)tok_alloc("Jan 1 1970", 0));
1380 } else if (tok
== TOK___TIME__
) {
1381 tok_add2(tok_str
, tok_len
, TOK_STR
,
1382 (int)tok_alloc("00:00:00", 0));
1383 } else if ((s
= sym_find1(&define_stack
, tok
)) != NULL
) {
1384 /* if symbol is a macro, prepare substitution */
1385 /* if nested substitution, do nothing */
1386 if (sym_find2(*nested_list
, tok
))
1390 if (s
->t
== MACRO_FUNC
) {
1391 /* NOTE: we do not use next_nomacro to avoid eating the
1392 next token. XXX: find better solution */
1396 while (ch
== ' ' || ch
== '\t' || ch
== '\n')
1400 if (t
!= '(') /* no macro subst */
1403 /* argument macro */
1408 while (tok
!= ')' && sa
) {
1412 while ((parlevel
> 0 ||
1415 sa
->v
== (TOK___VA_ARGS__
| SYM_FIELD
)))) &&
1419 else if (tok
== ')')
1421 tok_add2(&str
, &len
, tok
, tokc
);
1424 tok_add(&str
, &len
, 0);
1425 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, 0, (int)str
);
1433 /* now subst each arg */
1434 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
1445 sym_push2(nested_list
, s
->v
, 0, 0);
1446 macro_subst(tok_str
, tok_len
, nested_list
, mstr
);
1447 /* pop nested defined symbol */
1449 *nested_list
= sa1
->prev
;
1455 /* no need to add if reading input stream */
1458 tok_add2(tok_str
, tok_len
, tok
, tokc
);
1460 /* only replace one macro while parsing input stream */
1464 macro_ptr
= saved_macro_ptr
;
1469 /* return next token with macro substitution */
1475 /* special 'ungettok' case for label parsing */
1483 /* if not reading from macro substuted string, then try to substitute */
1487 macro_subst(&ptr
, &len
, &nested_list
, NULL
);
1489 tok_add(&ptr
, &len
, 0);
1491 macro_ptr_allocated
= ptr
;
1499 /* end of macro string: free it */
1500 free(macro_ptr_allocated
);
1507 printf("token = %s\n", get_tok_str(tok
, tokc
));
1511 void swap(int *p
, int *q
)
1525 /******************************************************/
1526 /* X86 code generator */
1528 typedef struct GFuncContext
{
1545 void gen_le32(int c
)
1553 /* add a new relocation entry to symbol 's' */
1554 void greloc(Sym
*s
, int addr
, int type
)
1557 p
= malloc(sizeof(Reloc
));
1559 error("memory full");
1562 p
->next
= (Reloc
*)s
->c
;
1566 /* patch each relocation entry with value 'val' */
1567 void greloc_patch(Sym
*s
, int val
)
1576 *(int *)p
->addr
= val
;
1579 *(int *)p
->addr
= val
- p
->addr
- 4;
1586 s
->t
&= ~VT_FORWARD
;
1589 /* output a symbol and patch all calls to it */
1590 void gsym_addr(t
, a
)
1594 n
= *(int *)t
; /* next value */
1595 *(int *)t
= a
- t
- 4;
1605 /* psym is used to put an instruction with a data field which is a
1606 reference to a symbol. It is in fact the same as oad ! */
1609 /* instruction + 4 bytes data. Return the address of the data */
1610 int oad(int c
, int s
)
1619 /* output constant with relocation if 't & VT_FORWARD' is true */
1620 void gen_addr32(int c
, int t
)
1622 if (!(t
& VT_FORWARD
)) {
1625 greloc((Sym
*)c
, ind
, RELOC_ADDR32
);
1630 /* XXX: generate correct pointer for forward references to functions */
1632 void load(r
, ft
, fc
)
1636 v
= ft
& VT_VALMASK
;
1638 if (v
== VT_LLOCAL
) {
1639 load(r
, VT_LOCAL
| VT_LVAL
, fc
);
1642 if ((ft
& VT_TYPE
) == VT_BYTE
)
1643 o(0xbe0f); /* movsbl */
1644 else if ((ft
& VT_TYPE
) == (VT_BYTE
| VT_UNSIGNED
))
1645 o(0xb60f); /* movzbl */
1646 else if ((ft
& VT_TYPE
) == VT_SHORT
)
1647 o(0xbf0f); /* movswl */
1648 else if ((ft
& VT_TYPE
) == (VT_SHORT
| VT_UNSIGNED
))
1649 o(0xb70f); /* movzwl */
1652 if (v
== VT_CONST
) {
1653 o(0x05 + r
* 8); /* 0xXX, r */
1655 } else if (v
== VT_LOCAL
) {
1656 oad(0x85 + r
* 8, fc
); /* xx(%ebp), r */
1658 g(0x00 + r
* 8 + v
); /* (v), r */
1661 if (v
== VT_CONST
) {
1662 o(0xb8 + r
); /* mov $xx, r */
1664 } else if (v
== VT_LOCAL
) {
1666 oad(0x85 + r
* 8, fc
); /* lea xxx(%ebp), r */
1667 } else if (v
== VT_CMP
) {
1668 oad(0xb8 + r
, 0); /* mov $0, r */
1669 o(0x0f); /* setxx %br */
1672 } else if (v
== VT_JMP
|| v
== VT_JMPI
) {
1674 oad(0xb8 + r
, t
); /* mov $1, r */
1675 oad(0xe9, 5); /* jmp after */
1677 oad(0xb8 + r
, t
^ 1); /* mov $0, r */
1678 } else if (v
!= r
) {
1680 o(0xc0 + r
+ v
* 8); /* mov v, r */
1686 /* WARNING: r must not be allocated on the stack */
1687 void store(r
, ft
, fc
)
1691 fr
= ft
& VT_VALMASK
;
1692 b
= (ft
& VT_TYPE
) == VT_BYTE
;
1693 /* XXX: incorrect if reg to reg */
1697 if (fr
== VT_CONST
) {
1698 o(0x05 + r
* 8); /* mov r,xxx */
1700 } else if (fr
== VT_LOCAL
) {
1701 oad(0x85 + r
* 8, fc
); /* mov r,xxx(%ebp) */
1702 } else if (ft
& VT_LVAL
) {
1703 g(fr
+ r
* 8); /* mov r, (fr) */
1704 } else if (fr
!= r
) {
1705 o(0xc0 + fr
+ r
* 8); /* mov r, fr */
1709 /* start function call and return function call context */
1710 void gfunc_start(GFuncContext
*c
)
1715 /* push function parameter which is in (vt, vc) */
1716 void gfunc_param(GFuncContext
*c
)
1718 int size
, align
, ft
, fc
, r
;
1720 if ((vt
& (VT_STRUCT
| VT_LVAL
)) == (VT_STRUCT
| VT_LVAL
)) {
1721 size
= type_size(vt
, &align
);
1722 /* align to stack align size */
1723 size
= (size
+ 3) & ~3;
1724 /* allocate the necessary size on stack */
1725 oad(0xec81, size
); /* sub $xxx, %esp */
1726 /* generate structure store */
1728 o(0x89); /* mov %esp, r */
1732 vset(VT_INT
| r
, 0);
1737 c
->args_size
+= size
;
1739 /* simple type (currently always same size) */
1740 /* XXX: implicit cast ? */
1742 o(0x50 + r
); /* push r */
1747 /* generate function call with address in (vt, vc) and free function
1749 void gfunc_call(GFuncContext
*c
)
1752 if ((vt
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
1754 /* forward reference */
1755 if (vt
& VT_FORWARD
) {
1756 greloc((Sym
*)vc
, ind
+ 1, RELOC_REL32
);
1759 oad(0xe8, vc
- ind
- 5);
1762 /* otherwise, indirect call */
1764 o(0xff); /* call *r */
1768 oad(0xc481, c
->args_size
); /* add $xxx, %esp */
1773 return psym(0xe9, t
);
1776 /* generate a test. set 'inv' to invert test */
1777 int gtst(int inv
, int t
)
1780 v
= vt
& VT_VALMASK
;
1782 /* fast case : can jump directly since flags are set */
1784 t
= psym((vc
- 16) ^ inv
, t
);
1785 } else if (v
== VT_JMP
|| v
== VT_JMPI
) {
1786 /* && or || optimization */
1787 if ((v
& 1) == inv
) {
1788 /* insert vc jump list in t */
1798 } else if ((vt
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
1799 /* constant jmp optimization */
1800 if ((vc
!= 0) != inv
)
1807 t
= psym(0x85 ^ inv
, t
);
1812 /* generate a binary operation 'v = r op fr' instruction and modifies
1813 (vt,vc) if needed */
1814 void gen_op1(int op
, int r
, int fr
)
1819 o(0xc0 + r
+ fr
* 8);
1820 } else if (op
== '-') {
1822 o(0xc0 + r
+ fr
* 8);
1823 } else if (op
== '&') {
1825 o(0xc0 + r
+ fr
* 8);
1826 } else if (op
== '^') {
1828 o(0xc0 + r
+ fr
* 8);
1829 } else if (op
== '|') {
1831 o(0xc0 + r
+ fr
* 8);
1832 } else if (op
== '*') {
1833 o(0xaf0f); /* imul fr, r */
1834 o(0xc0 + fr
+ r
* 8);
1835 } else if (op
== TOK_SHL
| op
== TOK_SHR
| op
== TOK_SAR
) {
1841 o(0x87); /* xchg r, %ecx */
1846 o(0xd3); /* shl/shr/sar %cl, r */
1849 else if (op
== TOK_SHR
)
1853 vt
= (vt
& VT_TYPE
) | r
;
1854 } else if (op
== '/' | op
== TOK_UDIV
| op
== TOK_PDIV
|
1855 op
== '%' | op
== TOK_UMOD
) {
1856 save_reg(2); /* save edx */
1857 t
= save_reg_forced(fr
); /* save fr and get op2 location */
1858 move_reg(0, r
); /* op1 is %eax */
1859 if (op
== TOK_UDIV
| op
== TOK_UMOD
) {
1860 o(0xf7d231); /* xor %edx, %edx, div t(%ebp), %eax */
1863 o(0xf799); /* cltd, idiv t(%ebp), %eax */
1866 if (op
== '%' | op
== TOK_UMOD
)
1870 vt
= (vt
& VT_TYPE
) | r
;
1873 o(0xc0 + r
+ fr
* 8); /* cmp fr, r */
1878 /* end of X86 code generator */
1879 /*************************************************************/
1881 int save_reg_forced(int r
)
1884 /* store register */
1885 loc
= (loc
- 4) & -3;
1886 store(r
, VT_LOCAL
, loc
);
1889 /* modify all stack values */
1890 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1891 i
= p
[0] & VT_VALMASK
;
1897 p
[0] = (p
[0] & VT_TYPE
) | VT_LVAL
| t
;
1904 /* save r to memory. and mark it as being free */
1909 /* modify all stack values */
1910 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1911 i
= p
[0] & VT_VALMASK
;
1919 /* find a free register. If none, save one register */
1924 /* find a free register */
1925 for(r
=0;r
<NB_REGS
;r
++) {
1926 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1927 i
= p
[0] & VT_VALMASK
;
1935 /* no register left : free the first one on the stack (very
1936 important to start from the bottom to ensure that we don't
1937 spill registers used in gen_op()) */
1938 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1939 r
= p
[0] & VT_VALMASK
;
1951 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1952 r
= p
[0] & VT_VALMASK
;
1959 /* move register 's' to 'r', and flush previous value of r to memory
1969 /* convert a stack entry in register. lvalues are converted as
1970 values. Cannot be used if cannot be converted to register value
1971 (such as structures). */
1975 r
= p
[0] & VT_VALMASK
;
1976 if (r
>= VT_CONST
|| (p
[0] & VT_LVAL
))
1978 /* NOTE: get_reg can modify p[] */
1979 load(r
, p
[0], p
[1]);
1980 p
[0] = (p
[0] & VT_TYPE
) | r
;
1986 if (vstack_ptr
>= vstack
+ VSTACK_SIZE
)
1987 error("memory full");
1990 /* cannot let cpu flags if other instruction are generated */
1991 /* XXX: VT_JMP test too ? */
1992 if ((vt
& VT_VALMASK
) == VT_CMP
)
1993 gvp(vstack_ptr
- 2);
1996 void vpop(int *ft
, int *fc
)
1998 *fc
= *--vstack_ptr
;
1999 *ft
= *--vstack_ptr
;
2002 /* generate a value in a register from vt and vc */
2007 r
= gvp(vstack_ptr
- 2);
2012 /* handle constant optimizations and various machine independant opt */
2015 int fr
, ft
, fc
, r
, c1
, c2
, n
;
2019 c1
= (vt
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
;
2020 c2
= (ft
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
;
2023 case '+': vc
+= fc
; break;
2024 case '-': vc
-= fc
; break;
2025 case '&': vc
&= fc
; break;
2026 case '^': vc
^= fc
; break;
2027 case '|': vc
|= fc
; break;
2028 case '*': vc
*= fc
; break;
2030 case '/': vc
/= fc
; break; /* XXX: zero case ? */
2031 case '%': vc
%= fc
; break; /* XXX: zero case ? */
2032 case TOK_UDIV
: vc
= (unsigned)vc
/ fc
; break; /* XXX: zero case ? */
2033 case TOK_UMOD
: vc
= (unsigned)vc
% fc
; break; /* XXX: zero case ? */
2034 case TOK_SHL
: vc
<<= fc
; break;
2035 case TOK_SHR
: vc
= (unsigned)vc
>> fc
; break;
2036 case TOK_SAR
: vc
>>= fc
; break;
2038 case TOK_ULT
: vc
= (unsigned)vc
< (unsigned)fc
; break;
2039 case TOK_UGE
: vc
= (unsigned)vc
>= (unsigned)fc
; break;
2040 case TOK_EQ
: vc
= vc
== fc
; break;
2041 case TOK_NE
: vc
= vc
!= fc
; break;
2042 case TOK_ULE
: vc
= (unsigned)vc
<= (unsigned)fc
; break;
2043 case TOK_UGT
: vc
= (unsigned)vc
> (unsigned)fc
; break;
2044 case TOK_LT
: vc
= vc
< fc
; break;
2045 case TOK_GE
: vc
= vc
>= fc
; break;
2046 case TOK_LE
: vc
= vc
<= fc
; break;
2047 case TOK_GT
: vc
= vc
> fc
; break;
2049 case TOK_LAND
: vc
= vc
&& fc
; break;
2050 case TOK_LOR
: vc
= vc
|| fc
; break;
2055 /* if commutative ops, put c2 as constant */
2056 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
2057 op
== '|' || op
== '*')) {
2062 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
2065 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
2066 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
2070 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
2071 /* try to use shifts instead of muls or divs */
2072 if (fc
> 0 && (fc
& (fc
- 1)) == 0) {
2081 else if (op
== TOK_PDIV
)
2093 r
= gvp(vstack_ptr
- 4);
2094 fr
= gvp(vstack_ptr
- 2);
2097 /* call low level op generator */
2103 int pointed_size(int t
)
2105 return type_size(pointed_type(t
), &t
);
2108 /* generic gen_op: handles types problems */
2114 t1
= vstack_ptr
[-4];
2115 t2
= vstack_ptr
[-2];
2116 if (op
== '+' | op
== '-') {
2117 if ((t1
& VT_PTR
) && (t2
& VT_PTR
)) {
2119 error("invalid type");
2120 /* XXX: check that types are compatible */
2121 u
= pointed_size(t1
);
2124 vstack_ptr
[-2] &= ~VT_TYPE
; /* set to integer */
2127 } else if ((t1
| t2
) & VT_PTR
) {
2129 swap(vstack_ptr
- 4, vstack_ptr
- 2);
2130 swap(vstack_ptr
- 3, vstack_ptr
- 1);
2133 /* stack-4 contains pointer, stack-2 value to add */
2134 vset(VT_CONST
, pointed_size(vstack_ptr
[-4]));
2138 /* put again type if gen_opc() swaped operands */
2139 vt
= (vt
& ~VT_TYPE
) | (t1
& VT_TYPE
);
2144 /* XXX: test types and compute returned value */
2145 if ((t1
| t2
) & (VT_UNSIGNED
| VT_PTR
)) {
2152 else if (op
== TOK_LT
)
2154 else if (op
== TOK_GT
)
2156 else if (op
== TOK_LE
)
2158 else if (op
== TOK_GE
)
2165 /* cast (vt, vc) to 't' type */
2166 void gen_cast(int t
)
2169 r
= vt
& VT_VALMASK
;
2170 if (!(t
& VT_LVAL
)) {
2171 /* if not lvalue, then we convert now */
2172 if ((t
& VT_TYPE
& ~VT_UNSIGNED
) == VT_BYTE
)
2174 else if ((t
& VT_TYPE
& ~VT_UNSIGNED
) == VT_SHORT
)
2179 if (t
& VT_UNSIGNED
) {
2180 vset(VT_CONST
, (1 << bits
) - 1);
2184 vset(VT_CONST
, bits
);
2187 vset(VT_CONST
, bits
);
2192 vt
= (vt
& ~VT_TYPE
) | t
;
2195 /* return type size. Put alignment at 'a' */
2196 int type_size(int t
, int *a
)
2200 /* int, enum or pointer */
2201 if (t
& VT_STRUCT
) {
2203 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
2204 *a
= 4; /* XXX: cannot store it yet. Doing that is safe */
2206 } else if (t
& VT_ARRAY
) {
2207 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
2208 return type_size(s
->t
, a
) * s
->c
;
2209 } else if ((t
& VT_PTR
) ||
2210 (t
& VT_TYPE
& ~VT_UNSIGNED
) == VT_INT
||
2214 } else if (t
& VT_SHORT
) {
2223 /* return the pointed type of t */
2224 int pointed_type(int t
)
2227 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
2228 return s
->t
| (t
& ~VT_TYPE
);
2231 int mk_pointer(int t
)
2236 return VT_PTR
| (p
<< VT_STRUCT_SHIFT
) | (t
& ~VT_TYPE
);
2239 /* store value in lvalue pushed on stack */
2242 int ft
, fc
, r
, t
, size
, align
;
2245 if (vt
& VT_STRUCT
) {
2246 /* if structure, only generate pointer */
2247 /* structure assignment : generate memcpy */
2248 /* XXX: optimize if small size */
2254 size
= type_size(vt
, &align
);
2255 vset(VT_CONST
, size
);
2267 vset(VT_CONST
, (int)&memcpy
);
2270 /* generate again current type */
2274 r
= gv(); /* generate value */
2276 ft
= vstack_ptr
[-4];
2277 fc
= vstack_ptr
[-3];
2278 /* if lvalue was saved on stack, must read it */
2279 if ((ft
& VT_VALMASK
) == VT_LLOCAL
) {
2281 load(t
, VT_LOCAL
| VT_LVAL
, fc
);
2282 ft
= (ft
& ~VT_VALMASK
) | t
;
2289 /* post defines POST/PRE add. c is the token ++ or -- */
2295 vpush(); /* room for returned value */
2296 vpush(); /* save lvalue */
2298 vpush(); /* save value */
2300 /* duplicate value */
2302 load(r1
, r
, 0); /* move r to r1 */
2303 vstack_ptr
[-6] = (vt
& VT_TYPE
) | r1
;
2307 vset(VT_CONST
, c
- TOK_MID
);
2309 vstore(); /* store value */
2314 /* enum/struct/union declaration */
2315 int struct_decl(int u
)
2317 int a
, t
, b
, v
, size
, align
, maxalign
, c
;
2320 a
= tok
; /* save decl type */
2325 /* struct already defined ? return it */
2326 /* XXX: check consistency */
2327 if (s
= sym_find(v
| SYM_STRUCT
)) {
2329 error("invalid type");
2335 s
= sym_push(v
| SYM_STRUCT
, a
, 0);
2336 /* put struct/union/enum name in type */
2338 u
= u
| (v
<< VT_STRUCT_SHIFT
);
2343 error("struct/union/enum already defined");
2344 /* cannot be empty */
2349 if (a
== TOK_ENUM
) {
2356 /* enum symbols have static storage */
2357 sym_push(v
, VT_CONST
| VT_STATIC
, c
);
2364 t
= type_decl(&v
, b
, TYPE_DIRECT
);
2365 if (t
& (VT_FUNC
| VT_TYPEDEF
))
2366 error("invalid type");
2367 /* XXX: align & correct type size */
2369 size
= type_size(t
, &align
);
2370 if (a
== TOK_STRUCT
) {
2371 c
= (c
+ align
- 1) & -align
;
2372 ss
= sym_push(v
, t
, c
);
2375 ss
= sym_push(v
, t
, 0);
2379 if (align
> maxalign
)
2383 if (tok
== ';' || tok
== -1)
2393 /* size for struct/union, dummy for enum */
2394 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
2399 /* return 0 if no type declaration. otherwise, return the basic type
2401 XXX: A '2' is ored to ensure non zero return if int type.
2410 if (tok
== TOK_ENUM
) {
2411 t
|= struct_decl(VT_ENUM
);
2412 } else if (tok
== TOK_STRUCT
|| tok
== TOK_UNION
) {
2413 t
|= struct_decl(VT_STRUCT
);
2415 if (tok
== TOK_CHAR
) {
2417 } else if (tok
== TOK_VOID
) {
2419 } else if (tok
== TOK_SHORT
) {
2421 } else if (tok
== TOK_INT
|
2422 (tok
>= TOK_CONST
& tok
<= TOK_INLINE
)) {
2424 } else if (tok
== TOK_FLOAT
|| tok
== TOK_DOUBLE
) {
2425 /* We allow that to compile standard headers */
2426 // warning("floats not supported");
2427 } else if (tok
== TOK_EXTERN
) {
2429 } else if (tok
== TOK_STATIC
) {
2431 } else if (tok
== TOK_UNSIGNED
) {
2433 } else if (tok
== TOK_TYPEDEF
) {
2437 if (!s
|| !(s
->t
& VT_TYPEDEF
))
2439 t
|= (s
->t
& ~VT_TYPEDEF
);
2448 int post_type(int t
)
2450 int p
, n
, pt
, l
, t1
;
2451 Sym
**plast
, *s
, *first
;
2454 /* function declaration */
2459 while (tok
!= ')') {
2460 /* read param name and compute offset */
2461 if (l
!= FUNC_OLD
) {
2462 if (!(pt
= ist())) {
2464 error("invalid type");
2470 if (pt
& VT_VOID
&& tok
== ')')
2473 pt
= type_decl(&n
, pt
, TYPE_DIRECT
| TYPE_ABSTRACT
);
2480 /* array must be transformed to pointer according to ANSI C */
2482 s
= sym_push(n
| SYM_FIELD
, pt
, 0);
2487 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
2495 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
2496 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
));
2497 /* we push a anonymous symbol which will contain the function prototype */
2499 s
= sym_push(p
, t
, l
);
2501 t
= t1
| VT_FUNC
| (p
<< VT_STRUCT_SHIFT
);
2502 } else if (tok
== '[') {
2503 /* array definition */
2509 error("invalid array size");
2512 /* parse next post type */
2513 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
2514 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
));
2516 /* we push a anonymous symbol which will contain the array
2520 t
= t1
| VT_ARRAY
| VT_PTR
| (p
<< VT_STRUCT_SHIFT
);
2525 /* Read a type declaration (except basic type), and return the
2526 type. If v is true, then also put variable name in 'vc' */
2527 int type_decl(int *v
, int t
, int td
)
2532 t
= t
& -3; /* suppress the ored '2' */
2533 while (tok
== '*') {
2535 while (tok
== TOK_CONST
|| tok
== TOK_VOLATILE
|| tok
== TOK_RESTRICT
)
2540 /* recursive type */
2541 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
2544 u
= type_decl(v
, 0, td
);
2548 /* type identifier */
2549 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
2553 if (!(td
& TYPE_ABSTRACT
))
2554 expect("identifier");
2558 /* append t at the end of u */
2564 s
= sym_find((unsigned)p
>> VT_STRUCT_SHIFT
);
2574 /* define a new external reference to a function 'v' of type 'u' */
2575 Sym
*external_sym(int v
, int u
)
2580 /* push forward reference */
2581 s
= sym_push1(&global_stack
,
2582 v
, u
| VT_CONST
| VT_FORWARD
, 0);
2593 vt
= pointed_type(vt
);
2594 if (!(vt
& VT_ARRAY
)) /* an array is never an lvalue */
2600 int n
, t
, ft
, fc
, p
, align
, size
;
2604 if (tok
== TOK_NUM
|| tok
== TOK_CCHAR
|| tok
== TOK_LCHAR
) {
2605 vset(VT_CONST
, tokc
);
2607 } else if (tok
== TOK___FUNC__
) {
2608 /* special function name identifier */
2609 /* generate (char *) type */
2610 vset(VT_CONST
| mk_pointer(VT_BYTE
), glo
);
2611 strcpy((void *)glo
, funcname
);
2612 glo
+= strlen(funcname
) + 1;
2614 } else if (tok
== TOK_LSTR
) {
2617 } else if (tok
== TOK_STR
) {
2618 /* string parsing */
2621 type_size(t
, &align
);
2622 glo
= (glo
+ align
- 1) & -align
;
2624 /* we must declare it as an array first to use initializer parser */
2625 t
= VT_CONST
| VT_ARRAY
| mk_pointer(t
);
2626 decl_initializer(t
, glo
, 1, 0);
2627 glo
+= type_size(t
, &align
);
2628 /* put it as pointer */
2629 vset(t
& ~VT_ARRAY
, fc
);
2636 ft
= type_decl(&n
, t
, TYPE_ABSTRACT
);
2638 /* check ISOC99 compound literal */
2640 /* data is allocated locally by default */
2645 /* all except arrays are lvalues */
2646 if (!(ft
& VT_ARRAY
))
2648 fc
= decl_initializer_alloc(ft
, 1);
2658 } else if (t
== '*') {
2661 } else if (t
== '&') {
2663 /* functions names must be treated as function pointers,
2664 except for unary '&' and sizeof. Since we consider that
2665 functions are not lvalues, we only have to handle it
2666 there and in function calls. */
2667 if (!(vt
& VT_FUNC
))
2669 vt
= mk_pointer(vt
& VT_LVALN
);
2673 if ((vt
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
)
2675 else if ((vt
& VT_VALMASK
) == VT_CMP
)
2678 vset(VT_JMP
, gtst(1, 0));
2689 if (t
== TOK_SIZEOF
) {
2690 /* XXX: some code can be generated */
2694 vt
= type_decl(&n
, t
, TYPE_ABSTRACT
);
2701 vset(VT_CONST
, type_size(vt
, &t
));
2703 if (t
== TOK_INC
| t
== TOK_DEC
) {
2706 } else if (t
== '-') {
2716 error("'%s' undeclared", get_tok_str(t
, 0));
2717 /* for simple function calls, we tolerate undeclared
2718 external reference */
2720 sym_push1(&global_stack
, p
, 0, FUNC_OLD
);
2721 /* int() function */
2722 s
= external_sym(t
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
));
2725 /* if forward reference, we must point to s */
2726 if (vt
& VT_FORWARD
)
2731 /* post operations */
2733 if (tok
== TOK_INC
| tok
== TOK_DEC
) {
2736 } else if (tok
== '.' | tok
== TOK_ARROW
) {
2738 if (tok
== TOK_ARROW
)
2743 /* expect pointer on structure */
2744 if (!(vt
& VT_STRUCT
))
2745 expect("struct or union");
2746 s
= sym_find(((unsigned)vt
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
2749 while (s
= s
->next
) {
2754 error("field not found");
2755 /* add field offset to pointer */
2756 vt
= (vt
& ~VT_TYPE
) | VT_INT
; /* change type to int */
2758 vset(VT_CONST
, s
->c
);
2760 /* change type to field type, and set to lvalue */
2761 vt
= (vt
& ~VT_TYPE
) | s
->t
;
2762 /* an array is never an lvalue */
2763 if (!(vt
& VT_ARRAY
))
2766 } else if (tok
== '[') {
2773 } else if (tok
== '(') {
2777 if (!(vt
& VT_FUNC
)) {
2778 if ((vt
& (VT_PTR
| VT_ARRAY
)) == VT_PTR
) {
2779 vt
= pointed_type(vt
);
2780 if (!(vt
& VT_FUNC
))
2784 expect("function pointer");
2787 vt
&= ~VT_LVAL
; /* no lvalue */
2790 /* get return type */
2791 s
= sym_find((unsigned)vt
>> VT_STRUCT_SHIFT
);
2792 vpush(); /* push function address */
2793 save_regs(); /* save used temporary registers */
2796 #ifdef INVERT_FUNC_PARAMS
2798 int *str
, len
, parlevel
, *saved_macro_ptr
;
2801 /* read each argument and store it on a stack */
2802 /* XXX: merge it with macro args ? */
2804 while (tok
!= ')') {
2808 while ((parlevel
> 0 || (tok
!= ')' && tok
!= ',')) &&
2812 else if (tok
== ')')
2814 tok_add2(&str
, &len
, tok
, tokc
);
2817 tok_add(&str
, &len
, -1); /* end of file added */
2818 tok_add(&str
, &len
, 0);
2819 sym_push2(&args
, 0, 0, (int)str
);
2827 /* now generate code in reverse order by reading the stack */
2828 saved_macro_ptr
= macro_ptr
;
2830 macro_ptr
= (int *)args
->c
;
2834 expect("',' or ')'");
2837 free((int *)args
->c
);
2841 macro_ptr
= saved_macro_ptr
;
2846 /* compute first implicit argument if a structure is returned */
2847 if (s
->t
& VT_STRUCT
) {
2848 /* get some space for the returned structure */
2849 size
= type_size(s
->t
, &align
);
2850 loc
= (loc
- size
) & -align
;
2851 rett
= s
->t
| VT_LOCAL
| VT_LVAL
;
2852 /* pass it as 'int' to avoid structure arg passing
2854 vset(VT_INT
| VT_LOCAL
, loc
);
2858 rett
= s
->t
| FUNC_RET_REG
; /* return in register */
2861 #ifndef INVERT_FUNC_PARAMS
2862 while (tok
!= ')') {
2881 int is_compatible_types(int t1
, int t2
)
2888 t1
= pointed_type(t1
);
2889 /* if function, then convert implictely to function pointer */
2890 if (!(t2
& VT_FUNC
)) {
2893 t2
= pointed_type(t2
);
2895 /* void matches everything */
2898 if (t1
== VT_VOID
|| t2
== VT_VOID
)
2900 return is_compatible_types(t1
, t2
);
2901 } else if (t1
& VT_STRUCT
) {
2903 } else if (t1
& VT_FUNC
) {
2904 if (!(t2
& VT_FUNC
))
2906 s1
= sym_find(((unsigned)t1
>> VT_STRUCT_SHIFT
));
2907 s2
= sym_find(((unsigned)t2
>> VT_STRUCT_SHIFT
));
2908 if (!is_compatible_types(s1
->t
, s2
->t
))
2910 /* XXX: not complete */
2911 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
2915 while (s1
!= NULL
) {
2918 if (!is_compatible_types(s1
->t
, s2
->t
))
2927 /* XXX: not complete */
2932 int check_assign_types(int t1
, int t2
)
2936 if ((t1
& VT_PTR
) && (t2
& VT_FUNC
)) {
2937 return is_compatible_types(pointed_type(t1
), t2
);
2939 return is_compatible_types(t1
, t2
);
2950 (tok
>= TOK_A_MOD
& tok
<= TOK_A_DIV
) |
2951 tok
== TOK_A_XOR
| tok
== TOK_A_OR
|
2952 tok
== TOK_A_SHL
| tok
== TOK_A_SAR
) {
2959 if (!check_assign_types(vstack_ptr
[-2], vt
))
2960 warning("incompatible types");
2978 while ((l
== 0 & (tok
== '*' | tok
== '/' | tok
== '%')) |
2979 (l
== 1 & (tok
== '+' | tok
== '-')) |
2980 (l
== 2 & (tok
== TOK_SHL
| tok
== TOK_SAR
)) |
2981 (l
== 3 & ((tok
>= TOK_ULE
& tok
<= TOK_GT
) |
2982 tok
== TOK_ULT
| tok
== TOK_UGE
)) |
2983 (l
== 4 & (tok
== TOK_EQ
| tok
== TOK_NE
)) |
2984 (l
== 5 & tok
== '&') |
2985 (l
== 6 & tok
== '^') |
2986 (l
== 7 & tok
== '|') |
2987 (l
== 8 & tok
== TOK_LAND
) |
2988 (l
== 9 & tok
== TOK_LOR
)) {
2998 /* only used if non constant */
3006 if (tok
!= TOK_LAND
) {
3026 if (tok
!= TOK_LOR
) {
3039 /* XXX: better constant handling */
3042 int t
, u
, c
, r1
, r2
;
3069 vt
= (vt
& VT_TYPE
) | r1
;
3091 if ((vt
& (VT_CONST
| VT_LVAL
)) != VT_CONST
)
3097 /* return the label token if current token is a label, otherwise
3103 /* fast test first */
3104 if (tok
< TOK_UIDENT
)
3113 /* XXX: may not work in all cases (macros ?) */
3122 void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
, int case_reg
)
3127 if (tok
== TOK_IF
) {
3134 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3136 if (c
== TOK_ELSE
) {
3140 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3141 gsym(d
); /* patch else jmp */
3144 } else if (tok
== TOK_WHILE
) {
3152 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
3153 oad(0xe9, d
- ind
- 5); /* jmp */
3156 } else if (tok
== '{') {
3159 s
= local_stack
.top
;
3160 while (tok
!= '}') {
3163 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3165 /* pop locally defined symbols */
3166 sym_pop(&local_stack
, s
);
3168 } else if (tok
== TOK_RETURN
) {
3171 if (func_vt
& VT_STRUCT
) {
3172 /* if returning structure, must copy it to implicit
3173 first pointer arg location */
3174 vset(mk_pointer(func_vt
) | VT_LOCAL
| VT_LVAL
, func_vc
);
3179 if (func_vt
& VT_STRUCT
) {
3180 /* copy structure value to pointer */
3183 /* move return value to standard return register */
3184 move_reg(FUNC_RET_REG
, gv());
3188 rsym
= gjmp(rsym
); /* jmp */
3189 } else if (tok
== TOK_BREAK
) {
3192 error("cannot break");
3193 *bsym
= gjmp(*bsym
);
3196 } else if (tok
== TOK_CONTINUE
) {
3199 error("cannot continue");
3200 *csym
= gjmp(*csym
);
3203 } else if (tok
== TOK_FOR
) {
3223 oad(0xe9, d
- ind
- 5); /* jmp */
3227 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
3228 oad(0xe9, c
- ind
- 5); /* jmp */
3232 if (tok
== TOK_DO
) {
3237 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
3248 if (tok
== TOK_SWITCH
) {
3257 block(&a
, csym
, &b
, &c
, case_reg
);
3258 /* if no default, jmp after switch */
3266 if (tok
== TOK_CASE
) {
3276 *case_sym
= gtst(1, 0);
3278 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3280 if (tok
== TOK_DEFAULT
) {
3286 error("too many 'default'");
3288 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3290 if (tok
== TOK_GOTO
) {
3292 s
= sym_find1(&label_stack
, tok
);
3293 /* put forward definition if needed */
3295 s
= sym_push1(&label_stack
, tok
, VT_FORWARD
, 0);
3296 /* label already defined */
3297 if (s
->t
& VT_FORWARD
)
3298 s
->c
= gjmp(s
->c
); /* jmp xxx */
3300 oad(0xe9, s
->c
- ind
- 5); /* jmp xxx */
3307 s
= sym_find1(&label_stack
, b
);
3309 if (!(s
->t
& VT_FORWARD
))
3310 error("multiple defined label");
3315 sym_push1(&label_stack
, b
, 0, ind
);
3317 /* we accept this, but it is a mistake */
3319 warning("deprecated use of label at end of compound statement");
3321 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3323 /* expression case */
3332 /* t is the array or struct type. c is the array or struct
3333 address. cur_index/cur_field is the pointer to the current
3334 value. 'size_only' is true if only size info is needed (only used
3336 void decl_designator(int t
, int c
,
3337 int *cur_index
, Sym
**cur_field
,
3341 int notfirst
, index
, align
, l
;
3344 if (gnu_ext
&& (l
= is_label()) != 0)
3347 while (tok
== '[' || tok
== '.') {
3349 if (!(t
& VT_ARRAY
))
3350 expect("array type");
3351 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3353 index
= expr_const();
3354 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
3355 expect("invalid index");
3359 t
= pointed_type(t
);
3360 c
+= index
* type_size(t
, &align
);
3366 if (!(t
& VT_STRUCT
))
3367 expect("struct/union type");
3368 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
3380 t
= f
->t
| (t
& ~VT_TYPE
);
3395 t
= pointed_type(t
);
3396 c
+= index
* type_size(t
, &align
);
3400 error("too many field init");
3401 t
= f
->t
| (t
& ~VT_TYPE
);
3405 decl_initializer(t
, c
, 0, size_only
);
3408 /* store a value or an expression directly in global data or in local array */
3410 void init_putv(int t
, int c
, int v
, int is_expr
)
3412 int saved_global_expr
;
3414 if ((t
& VT_VALMASK
) == VT_CONST
) {
3416 /* compound literals must be allocated globally in this case */
3417 saved_global_expr
= global_expr
;
3420 global_expr
= saved_global_expr
;
3424 else if (t
& VT_SHORT
)
3440 /* put zeros for variable based init */
3441 void init_putz(int t
, int c
, int size
)
3445 if ((t
& VT_VALMASK
) == VT_CONST
) {
3446 /* nothing to do because global are already set to zero */
3449 vset(VT_CONST
, size
);
3455 vset(VT_CONST
, (int)&memset
);
3460 /* 't' contains the type and storage info. c is the address of the
3461 object. 'first' is true if array '{' must be read (multi dimension
3462 implicit array init handling). 'size_only' is true if size only
3463 evaluation is wanted (only for arrays). */
3464 void decl_initializer(int t
, int c
, int first
, int size_only
)
3466 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
3467 int t1
, size1
, align1
;
3472 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3475 t1
= pointed_type(t
);
3476 size1
= type_size(t1
, &align1
);
3479 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
3485 /* only parse strings here if correct type (otherwise: handle
3486 them as ((w)char *) expressions */
3487 if ((tok
== TOK_LSTR
&&
3488 (t1
& VT_TYPE
& ~VT_UNSIGNED
) == VT_INT
) ||
3490 (t1
& VT_TYPE
& ~VT_UNSIGNED
) == VT_BYTE
)) {
3491 /* XXX: move multiple string parsing in parser ? */
3492 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
3493 ts
= (TokenSym
*)tokc
;
3494 /* compute maximum number of chars wanted */
3496 if (n
>= 0 && nb
> (n
- array_length
))
3497 nb
= n
- array_length
;
3500 warning("initializer-string for array is too long");
3502 init_putv(t1
, c
+ (array_length
+ i
) * size1
,
3509 /* only add trailing zero if enough storage (no
3510 warning in this case since it is standard) */
3511 if (n
< 0 || array_length
< n
) {
3513 init_putv(t1
, c
+ (array_length
* size1
), 0, 0);
3519 while (tok
!= '}') {
3520 decl_designator(t
, c
, &index
, NULL
, size_only
);
3521 if (n
>= 0 && index
>= n
)
3522 error("index too large");
3523 /* must put zero in holes (note that doing it that way
3524 ensures that it even works with designators) */
3525 if (!size_only
&& array_length
< index
) {
3526 init_putz(t1
, c
+ array_length
* size1
,
3527 (index
- array_length
) * size1
);
3530 if (index
> array_length
)
3531 array_length
= index
;
3532 /* special test for multi dimensional arrays (may not
3533 be strictly correct if designators are used at the
3535 if (index
>= n
&& no_oblock
)
3544 /* put zeros at the end */
3545 if (!size_only
&& n
>= 0 && array_length
< n
) {
3546 init_putz(t1
, c
+ array_length
* size1
,
3547 (n
- array_length
) * size1
);
3549 /* patch type size if needed */
3551 s
->c
= array_length
;
3552 } else if ((t
& VT_STRUCT
) && tok
== '{') {
3553 /* XXX: union needs only one init */
3555 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
3560 while (tok
!= '}') {
3561 decl_designator(t
, c
, NULL
, &f
, size_only
);
3562 /* fill with zero between fields */
3564 if (!size_only
&& array_length
< index
) {
3565 init_putz(t
, c
+ array_length
,
3566 index
- array_length
);
3568 index
= index
+ type_size(f
->t
, &align1
);
3569 if (index
> array_length
)
3570 array_length
= index
;
3576 /* put zeros at the end */
3577 if (!size_only
&& array_length
< n
) {
3578 init_putz(t
, c
+ array_length
,
3582 } else if (tok
== '{') {
3584 decl_initializer(t
, c
, first
, size_only
);
3586 } else if (size_only
) {
3587 /* just skip expression */
3589 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
3593 else if (tok
== ')')
3598 init_putv(t
, c
, 0, 1);
3602 /* parse an initializer for type 't' if 'has_init' is true, and
3603 allocate space in local or global data space. The allocated address
3605 int decl_initializer_alloc(int t
, int has_init
)
3607 int size
, align
, addr
, tok1
;
3608 int *init_str
, init_len
, level
, *saved_macro_ptr
;
3610 size
= type_size(t
, &align
);
3611 /* If unknown size, we must evaluate it before
3612 evaluating initializers because
3613 initializers can generate global data too
3614 (e.g. string pointers or ISOC99 compound
3615 literals). It also simplifies local
3616 initializers handling */
3619 saved_macro_ptr
= NULL
; /* avoid warning */
3623 error("unknown type size");
3624 /* get all init string */
3626 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
3628 error("unexpect end of file in initializer");
3629 tok_add2(&init_str
, &init_len
, tok
, tokc
);
3632 else if (tok
== '}') {
3640 tok_add(&init_str
, &init_len
, -1);
3641 tok_add(&init_str
, &init_len
, 0);
3644 saved_macro_ptr
= macro_ptr
;
3645 macro_ptr
= init_str
;
3647 decl_initializer(t
, 0, 1, 1);
3648 /* prepare second initializer parsing */
3649 macro_ptr
= init_str
;
3652 /* if still unknown size, error */
3653 size
= type_size(t
, &align
);
3655 error("unknown type size");
3657 if ((t
& VT_VALMASK
) == VT_LOCAL
) {
3658 loc
= (loc
- size
) & -align
;
3661 glo
= (glo
+ align
- 1) & -align
;
3663 /* very important to increment global
3664 pointer at this time because
3665 initializers themselves can create new
3670 decl_initializer(t
, addr
, 1, 0);
3671 /* restore parse state if needed */
3674 macro_ptr
= saved_macro_ptr
;
3682 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
3685 int *a
, t
, b
, v
, u
, addr
, has_init
, size
, align
;
3691 /* skip redundant ';' */
3692 /* XXX: find more elegant solution */
3697 /* special test for old K&R protos without explicit int
3698 type. Only accepted when defining global data */
3699 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
3703 if ((b
& (VT_ENUM
| VT_STRUCT
)) && tok
== ';') {
3704 /* we accept no variable after */
3708 while (1) { /* iterate thru each declaration */
3709 t
= type_decl(&v
, b
, TYPE_DIRECT
);
3712 error("cannot use local functions");
3714 expect("function definition");
3715 /* patch forward references */
3716 if ((sym
= sym_find(v
)) && (sym
->t
& VT_FORWARD
)) {
3717 greloc_patch(sym
, ind
);
3718 sym
->t
= VT_CONST
| t
;
3720 /* put function address */
3721 sym_push1(&global_stack
, v
, VT_CONST
| t
, ind
);
3723 funcname
= get_tok_str(v
, 0);
3724 /* push a dummy symbol to enable local sym storage */
3725 sym_push1(&local_stack
, 0, 0, 0);
3726 /* define parameters */
3727 sym
= sym_find((unsigned)t
>> VT_STRUCT_SHIFT
);
3728 /* XXX: the following is x86 dependant -> move it to
3731 /* if the function returns a structure, then add an
3732 implicit pointer parameter */
3734 if (func_vt
& VT_STRUCT
) {
3738 while (sym
= sym
->next
) {
3740 sym_push(sym
->v
& ~SYM_FIELD
,
3741 u
| VT_LOCAL
| VT_LVAL
,
3743 if (u
& VT_STRUCT
) {
3744 #ifdef FUNC_STRUCT_PARAM_AS_PTR
3745 /* structs are passed as pointer */
3748 /* structs are directly put on stack (x86
3750 size
= type_size(u
, &align
);
3751 size
= (size
+ 3) & ~3;
3754 /* XXX: size will be different someday */
3760 o(0xe58955); /* push %ebp, mov %esp, %ebp */
3761 a
= (int *)oad(0xec81, 0); /* sub $xxx, %esp */
3763 block(0, 0, 0, 0, 0);
3765 o(0xc3c9); /* leave, ret */
3766 *a
= (-loc
+ 3) & -4; /* align local size to word &
3767 save local variables */
3768 sym_pop(&label_stack
, 0); /* reset label stack */
3769 sym_pop(&local_stack
, 0); /* reset local stack */
3770 funcname
= ""; /* for safety */
3771 func_vt
= VT_VOID
; /* for safety */
3774 if (b
& VT_TYPEDEF
) {
3775 /* save typedefed type */
3776 /* XXX: test storage specifiers ? */
3777 sym_push(v
, t
| VT_TYPEDEF
, 0);
3778 } else if (t
& VT_FUNC
) {
3779 /* external function definition */
3782 /* not lvalue if array */
3783 if (!(t
& VT_ARRAY
))
3785 if (b
& VT_EXTERN
) {
3786 /* external variable */
3793 has_init
= (tok
== '=');
3796 addr
= decl_initializer_alloc(u
, has_init
);
3797 if (l
== VT_CONST
) {
3798 /* global scope: see if already defined */
3802 if (!is_compatible_types(sym
->t
, u
))
3803 error("incompatible types for redefinition of '%s'",
3805 if (!(sym
->t
& VT_FORWARD
))
3806 error("redefinition of '%s'", get_tok_str(v
, 0));
3807 greloc_patch(sym
, addr
);
3810 sym_push(v
, u
, addr
);
3824 /* put all global symbols in the extern stack and do all the
3825 resolving which can be done without using external symbols from DLLs */
3826 /* XXX: could try to verify types, but would not to save them in
3828 void resolve_global_syms(void)
3830 Sym
*s
, *s1
, *ext_sym
;
3833 s
= global_stack
.top
;
3836 /* do not save static or typedefed symbols or types */
3837 if (!(s
->t
& (VT_STATIC
| VT_TYPEDEF
)) &&
3838 !(s
->v
& (SYM_FIELD
| SYM_STRUCT
)) &&
3839 (s
->v
< SYM_FIRST_ANOM
)) {
3840 ext_sym
= sym_find1(&extern_stack
, s
->v
);
3842 /* if the symbol do not exist, we simply save it */
3843 sym_push1(&extern_stack
, s
->v
, s
->t
, s
->c
);
3844 } else if (ext_sym
->t
& VT_FORWARD
) {
3845 /* external symbol already exists, but only as forward
3847 if (!(s
->t
& VT_FORWARD
)) {
3848 /* s is not forward, so we can relocate all symbols */
3849 greloc_patch(ext_sym
, s
->c
);
3851 /* the two symbols are forward: merge them */
3852 p
= (Reloc
**)&ext_sym
->c
;
3858 /* external symbol already exists and is defined :
3859 patch all references to it */
3860 if (!(s
->t
& VT_FORWARD
))
3861 error("'%s' defined twice", get_tok_str(s
->v
, 0));
3862 greloc_patch(s
, ext_sym
->c
);
3869 /* compile a C file. Return non zero if errors. */
3870 int tcc_compile_file(const char *filename1
)
3874 filename
= (char *)filename1
;
3878 file
= fopen(filename
, "r");
3880 error("file '%s' not found", filename
);
3881 include_stack_ptr
= include_stack
;
3882 ifdef_stack_ptr
= ifdef_stack
;
3884 vstack_ptr
= vstack
;
3885 anon_sym
= SYM_FIRST_ANOM
;
3887 define_start
= define_stack
.top
;
3889 ch
= '\n'; /* needed to parse correctly first preprocessor command */
3893 expect("declaration");
3896 /* reset define stack, but leave -Dsymbols (may be incorrect if
3897 they are undefined) */
3898 sym_pop(&define_stack
, define_start
);
3900 resolve_global_syms();
3902 sym_pop(&global_stack
, NULL
);
3907 /* open a dynamic library so that its symbol are available for
3908 compiled programs */
3909 void open_dll(char *libname
)
3914 snprintf(buf
, sizeof(buf
), "lib%s.so", libname
);
3915 h
= dlopen(buf
, RTLD_GLOBAL
| RTLD_LAZY
);
3917 error((char *)dlerror());
3920 void resolve_extern_syms(void)
3926 s
= extern_stack
.top
;
3929 if (s
->t
& VT_FORWARD
) {
3930 /* if there is at least one relocation to do, then find it
3933 str
= get_tok_str(s
->v
, 0);
3934 addr
= (int)dlsym(NULL
, str
);
3936 error("unresolved external reference '%s'", str
);
3937 greloc_patch(s
, addr
);
3944 /* output a binary file (for testing) */
3945 void build_exe(char *filename
)
3948 f
= fopen(filename
, "w");
3949 fwrite((void *)prog
, 1, ind
- prog
, f
);
3953 int main(int argc
, char **argv
)
3957 char *p
, *r
, *outfile
;
3960 include_paths
[0] = "/usr/include";
3961 include_paths
[1] = "/usr/lib/tcc";
3962 include_paths
[2] = "/usr/local/lib/tcc";
3963 nb_include_paths
= 3;
3965 /* add all tokens */
3966 tok_ident
= TOK_IDENT
;
3967 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\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";
3971 tok_alloc(p
, r
- p
- 1);
3975 /* standard defines */
3976 define_symbol("__STDC__");
3978 define_symbol("__i386__");
3980 /* tiny C specific defines */
3981 define_symbol("__TINYC__");
3983 glo
= (int)malloc(DATA_SIZE
);
3984 memset((void *)glo
, 0, DATA_SIZE
);
3985 prog
= (int)malloc(TEXT_SIZE
);
3991 if (optind
>= argc
) {
3993 printf("tcc version 0.9.1 - Tiny C Compiler - Copyright (C) 2001 Fabrice Bellard\n"
3994 "usage: tcc [-Idir] [-Dsym] [-llib] [-i infile]... infile [infile_args...]\n");
4002 if (nb_include_paths
>= INCLUDE_PATHS_MAX
)
4003 error("too many include paths");
4004 include_paths
[nb_include_paths
++] = r
+ 2;
4005 } else if (r
[1] == 'D') {
4006 define_symbol(r
+ 2);
4007 } else if (r
[1] == 'l') {
4009 } else if (r
[1] == 'i') {
4012 tcc_compile_file(argv
[optind
++]);
4013 } else if (r
[1] == 'o') {
4014 /* currently, only for testing, so not documented */
4017 outfile
= argv
[optind
++];
4019 fprintf(stderr
, "invalid option -- '%s'\n", r
);
4024 tcc_compile_file(argv
[optind
]);
4026 resolve_extern_syms();
4032 s
= sym_find1(&extern_stack
, TOK_MAIN
);
4033 if (!s
|| (s
->t
& VT_FORWARD
))
4034 error("main() not defined");
4035 t
= (int (*)())s
->c
;
4036 return (*t
)(argc
- optind
, argv
+ optind
);