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 /* token symbol management */
47 typedef struct TokenSym
{
48 struct TokenSym
*hash_next
;
49 int tok
; /* token number */
54 /* symbol management */
56 int v
; /* symbol token */
57 int t
; /* associated type */
58 int c
; /* associated number */
59 struct Sym
*next
; /* next related symbol */
60 struct Sym
*prev
; /* prev symbol in stack */
61 struct Sym
*hash_next
; /* next symbol in hash table */
64 typedef struct SymStack
{
66 struct Sym
*hash
[SYM_HASH_SIZE
];
69 /* relocation entry (currently only used for functions or variables */
70 typedef struct Reloc
{
71 int type
; /* type of relocation */
72 int addr
; /* address of relocation */
73 struct Reloc
*next
; /* next relocation */
76 #define RELOC_ADDR32 1 /* 32 bits relocation */
77 #define RELOC_REL32 2 /* 32 bits relative relocation */
80 #define SYM_STRUCT 0x40000000 /* struct/union/enum symbol space */
81 #define SYM_FIELD 0x20000000 /* struct/union field symbol space */
82 #define SYM_FIRST_ANOM (1 << (31 - VT_STRUCT_SHIFT)) /* first anonymous sym */
84 #define FUNC_NEW 1 /* ansi function prototype */
85 #define FUNC_OLD 2 /* old function prototype */
86 #define FUNC_ELLIPSIS 3 /* ansi function prototype with ... */
88 /* field 'Sym.t' for macros */
89 #define MACRO_OBJ 0 /* object like macro */
90 #define MACRO_FUNC 1 /* function like macro */
92 /* type_decl() types */
93 #define TYPE_ABSTRACT 1 /* type without variable */
94 #define TYPE_DIRECT 2 /* type with variable */
104 int ch
, ch1
, tok
, tokc
, tok1
, tok1c
;
106 /* loc : local variable index
107 glo : global variable index
108 ind : output code ptr
111 anon_sym: anonymous symbol index
114 prog
, ind
, loc
, glo
, vt
, vc
, const_wanted
, line_num
;
115 int global_expr
; /* true if compound literals must be allocated
116 globally (used during initializers parsing */
117 int func_vt
, func_vc
; /* current function return type (used by
118 return instruction) */
120 TokenSym
**table_ident
;
121 TokenSym
*hash_ident
[TOK_HASH_SIZE
];
122 char token_buf
[STRING_MAX_SIZE
+ 1];
123 char *filename
, *funcname
;
124 /* contains global symbols which remain between each translation unit */
125 SymStack extern_stack
;
126 SymStack define_stack
, global_stack
, local_stack
, label_stack
;
128 int vstack
[VSTACK_SIZE
], *vstack_ptr
;
129 int *macro_ptr
, *macro_ptr_allocated
;
130 IncludeFile include_stack
[INCLUDE_STACK_SIZE
], *include_stack_ptr
;
131 int ifdef_stack
[IFDEF_STACK_SIZE
], *ifdef_stack_ptr
;
132 char *include_paths
[INCLUDE_PATHS_MAX
];
133 int nb_include_paths
;
135 /* use GNU C extensions */
138 /* The current value can be: */
139 #define VT_VALMASK 0x000f
140 #define VT_CONST 0x000a /* constant in vc
141 (must be first non register value) */
142 #define VT_LLOCAL 0x000b /* lvalue, offset on stack */
143 #define VT_LOCAL 0x000c /* offset on stack */
144 #define VT_CMP 0x000d /* the value is stored in processor flags (in vc) */
145 #define VT_JMP 0x000e /* value is the consequence of jmp true */
146 #define VT_JMPI 0x000f /* value is the consequence of jmp false */
147 #define VT_LVAL 0x0010 /* var is an lvalue */
148 #define VT_LVALN -17 /* ~VT_LVAL */
149 #define VT_FORWARD 0x0020 /* value is forward reference
150 (only used for functions) */
152 #define VT_EXTERN 0x00000040 /* extern definition */
153 #define VT_STATIC 0x00000080 /* static variable */
154 #define VT_TYPEDEF 0x00000100 /* typedef definition */
157 #define VT_STRUCT_SHIFT 16 /* structure/enum name shift (16 bits left) */
159 #define VT_BTYPE_SHIFT 9
160 #define VT_INT (0 << VT_BTYPE_SHIFT) /* integer type */
161 #define VT_BYTE (1 << VT_BTYPE_SHIFT) /* signed byte type */
162 #define VT_SHORT (2 << VT_BTYPE_SHIFT) /* short type */
163 #define VT_VOID (3 << VT_BTYPE_SHIFT) /* void type */
164 #define VT_PTR (4 << VT_BTYPE_SHIFT) /* pointer increment */
165 #define VT_ENUM (5 << VT_BTYPE_SHIFT) /* enum definition */
166 #define VT_FUNC (6 << VT_BTYPE_SHIFT) /* function type */
167 #define VT_STRUCT (7 << VT_BTYPE_SHIFT) /* struct/union definition */
168 #define VT_FLOAT (8 << VT_BTYPE_SHIFT) /* IEEE float */
169 #define VT_DOUBLE (9 << VT_BTYPE_SHIFT) /* IEEE double */
170 #define VT_BOOL (10 << VT_BTYPE_SHIFT) /* ISOC99 boolean type */
171 #define VT_BTYPE (0xf << VT_BTYPE_SHIFT) /* mask for basic type */
172 #define VT_UNSIGNED (0x10 << VT_BTYPE_SHIFT) /* unsigned type */
173 #define VT_ARRAY (0x20 << VT_BTYPE_SHIFT) /* array type (also has VT_PTR) */
174 #define VT_BITFIELD (0x40 << VT_BTYPE_SHIFT) /* bitfield modifier */
176 #define VT_TYPE 0xfffffe00 /* type mask */
180 /* warning: the following compare tokens depend on i386 asm code */
192 #define TOK_LAND 0xa0
196 #define TOK_MID 0xa3 /* inc/dec, to void constant */
198 #define TOK_ARROW 0xa7
199 #define TOK_DOTS 0xa8 /* three dots */
200 #define TOK_SHR 0xa9 /* unsigned shift right */
201 #define TOK_UDIV 0xb0 /* unsigned division */
202 #define TOK_UMOD 0xb1 /* unsigned modulo */
203 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
204 #define TOK_NUM 0xb3 /* number in tokc */
205 #define TOK_CCHAR 0xb4 /* char constant in tokc */
206 #define TOK_STR 0xb5 /* pointer to string in tokc */
207 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
208 #define TOK_LCHAR 0xb7
209 #define TOK_LSTR 0xb8
211 #define TOK_SHL 0x01 /* shift left */
212 #define TOK_SAR 0x02 /* signed shift right */
214 /* assignement operators : normal operator or 0x80 */
215 #define TOK_A_MOD 0xa5
216 #define TOK_A_AND 0xa6
217 #define TOK_A_MUL 0xaa
218 #define TOK_A_ADD 0xab
219 #define TOK_A_SUB 0xad
220 #define TOK_A_DIV 0xaf
221 #define TOK_A_XOR 0xde
222 #define TOK_A_OR 0xfc
223 #define TOK_A_SHL 0x81
224 #define TOK_A_SAR 0x82
226 /* all identificators and strings have token above that */
227 #define TOK_IDENT 256
248 /* ignored types Must have contiguous values */
258 /* unsupported type */
271 /* preprocessor only */
272 TOK_UIDENT
, /* first "user" ident (not keyword) */
273 TOK_DEFINE
= TOK_UIDENT
,
289 /* special identifiers */
301 void decl_initializer(int t
, int c
, int first
, int size_only
);
302 int decl_initializer_alloc(int t
, int has_init
);
304 void move_reg(int r
, int s
);
305 void save_reg(int r
);
307 void vpop(int *ft
, int *fc
);
311 void macro_subst(int **tok_str
, int *tok_len
,
312 Sym
**nested_list
, int *macro_str
);
313 int save_reg_forced(int r
);
315 void gen_cast(int t
);
317 int type_size(int t
, int *a
);
318 int pointed_type(int t
);
319 int pointed_size(int t
);
321 int type_decl(int *v
, int t
, int td
);
323 #ifdef CONFIG_TCC_STATIC
325 #define RTLD_LAZY 0x001
326 #define RTLD_NOW 0x002
327 #define RTLD_GLOBAL 0x100
329 /* dummy function for profiling */
330 void *dlopen(const char *filename
, int flag
)
335 const char *dlerror(void)
340 typedef struct TCCSyms
{
345 #define TCCSYM(a) { #a, &a, },
347 /* add the symbol you want here if no dynamic linking is done */
348 static TCCSyms tcc_syms
[] = {
356 void *dlsym(void *handle
, char *symbol
)
360 while (p
->str
!= NULL
) {
361 if (!strcmp(p
->str
, symbol
))
370 inline int isid(int c
)
372 return (c
>= 'a' && c
<= 'z') ||
373 (c
>= 'A' && c
<= 'Z') ||
377 inline int isnum(int c
)
379 return c
>= '0' & c
<= '9';
385 for(f
= include_stack
; f
< include_stack_ptr
; f
++)
386 fprintf(stderr
, "In file included from %s:%d:\n",
387 f
->filename
, f
->line_num
);
388 fprintf(stderr
, "%s:%d: ", filename
, line_num
);
391 void error(const char *fmt
, ...)
396 vfprintf(stderr
, fmt
, ap
);
397 fprintf(stderr
, "\n");
402 void expect(const char *msg
)
404 error("%s expected", msg
);
407 void warning(const char *msg
)
410 fprintf(stderr
, "warning: %s\n", msg
);
416 error("'%c' expected", c
);
420 void test_lvalue(void)
426 TokenSym
*tok_alloc(char *str
, int len
)
428 TokenSym
*ts
, **pts
, **ptable
;
435 h
= ((h
<< 8) | (str
[i
] & 0xff)) % TOK_HASH_SIZE
;
437 pts
= &hash_ident
[h
];
442 if (ts
->len
== len
&& !memcmp(ts
->str
, str
, len
))
444 pts
= &(ts
->hash_next
);
447 if (tok_ident
>= SYM_FIRST_ANOM
)
448 error("memory full");
450 /* expand token table if needed */
451 i
= tok_ident
- TOK_IDENT
;
452 if ((i
% TOK_ALLOC_INCR
) == 0) {
453 ptable
= realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
455 error("memory full");
456 table_ident
= ptable
;
459 ts
= malloc(sizeof(TokenSym
) + len
);
461 error("memory full");
463 ts
->tok
= tok_ident
++;
465 ts
->hash_next
= NULL
;
466 memcpy(ts
->str
, str
, len
+ 1);
471 void add_char(char **pp
, int c
)
475 if (c
== '\'' || c
== '\"' || c
== '\\') {
476 /* XXX: could be more precise if char or string */
479 if (c
>= 32 && c
<= 126) {
486 *p
++ = '0' + ((c
>> 6) & 7);
487 *p
++ = '0' + ((c
>> 3) & 7);
488 *p
++ = '0' + (c
& 7);
494 /* XXX: buffer overflow */
495 char *get_tok_str(int v
, int c
)
497 static char buf
[STRING_MAX_SIZE
+ 1];
503 sprintf(buf
, "%d", c
);
505 } else if (v
== TOK_CCHAR
|| v
== TOK_LCHAR
) {
512 } else if (v
== TOK_STR
|| v
== TOK_LSTR
) {
516 for(i
=0;i
<ts
->len
;i
++)
517 add_char(&p
, ts
->str
[i
]);
521 } else if (v
< TOK_IDENT
) {
526 } else if (v
< tok_ident
) {
527 return table_ident
[v
- TOK_IDENT
]->str
;
529 /* should never happen */
534 /* push, without hashing */
535 Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
538 s
= malloc(sizeof(Sym
));
540 error("memory full");
551 /* find a symbol and return its associated structure. 's' is the top
552 of the symbol stack */
553 Sym
*sym_find2(Sym
*s
, int v
)
563 #define HASH_SYM(v) ((unsigned)(v) % SYM_HASH_SIZE)
565 /* find a symbol and return its associated structure. 'st' is the
567 Sym
*sym_find1(SymStack
*st
, int v
)
571 s
= st
->hash
[HASH_SYM(v
)];
580 Sym
*sym_push1(SymStack
*st
, int v
, int t
, int c
)
583 s
= sym_push2(&st
->top
, v
, t
, c
);
584 /* add in hash table */
586 ps
= &st
->hash
[HASH_SYM(v
)];
593 /* find a symbol in the right symbol space */
597 s
= sym_find1(&local_stack
, v
);
599 s
= sym_find1(&global_stack
, v
);
603 /* push a given symbol on the symbol stack */
604 Sym
*sym_push(int v
, int t
, int c
)
607 return sym_push1(&local_stack
, v
, t
, c
);
609 return sym_push1(&global_stack
, v
, t
, c
);
612 /* pop symbols until top reaches 'b' */
613 void sym_pop(SymStack
*st
, Sym
*b
)
620 /* free hash table entry, except if symbol was freed (only
621 used for #undef symbols) */
623 st
->hash
[HASH_SYM(s
->v
)] = s
->hash_next
;
630 /* undefined a hashed symbol (used for #undef). Its name is set to
632 void sym_undef(SymStack
*st
, Sym
*s
)
635 ss
= &st
->hash
[HASH_SYM(s
->v
)];
636 while (*ss
!= NULL
) {
639 ss
= &(*ss
)->hash_next
;
645 /* no need to put that inline */
648 if (include_stack_ptr
== include_stack
)
650 /* pop include stack */
654 file
= include_stack_ptr
->file
;
655 filename
= include_stack_ptr
->filename
;
656 line_num
= include_stack_ptr
->line_num
;
660 /* read next char from current input file */
661 static inline void inp(void)
664 /* faster than fgetc */
665 ch1
= getc_unlocked(file
);
667 if (handle_eof() < 0)
674 // printf("ch1=%c 0x%x\n", ch1, ch1);
677 /* input with '\\n' handling */
678 static inline void minp(void)
683 if (ch
== '\\' && ch1
== '\n') {
687 //printf("ch=%c 0x%x\n", ch, ch);
691 /* same as minp, but also skip comments */
699 /* single line C++ comments */
701 while (ch1
!= '\n' && ch1
!= -1)
704 ch
= ' '; /* return space */
705 } else if (ch1
== '*') {
711 if (c
== '*' && ch1
== '/') {
713 ch
= ' '; /* return space */
725 void skip_spaces(void)
727 while (ch
== ' ' || ch
== '\t')
731 /* skip block of text until #else, #elif or #endif. skip also pairs of
733 void preprocess_skip()
749 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
751 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
753 else if (tok
== TOK_ENDIF
)
759 inline int is_long_tok(int t
)
761 return (t
== TOK_NUM
||
762 t
== TOK_CCHAR
|| t
== TOK_LCHAR
||
763 t
== TOK_STR
|| t
== TOK_LSTR
);
766 void tok_add(int **tok_str
, int *tok_len
, int t
)
771 if ((len
& 63) == 0) {
772 str
= realloc(str
, (len
+ 64) * sizeof(int));
781 void tok_add2(int **tok_str
, int *tok_len
, int t
, int c
)
783 tok_add(tok_str
, tok_len
, t
);
785 tok_add(tok_str
, tok_len
, c
);
788 /* eval an expression for #if/#elif */
789 int expr_preprocess()
799 next(); /* do macro subst */
800 if (tok
== TOK_DEFINED
) {
805 c
= sym_find1(&define_stack
, tok
) != 0;
810 } else if (tok
>= TOK_IDENT
) {
811 /* if undefined macro */
815 tok_add2(&str
, &len
, tok
, tokc
);
817 tok_add(&str
, &len
, -1); /* simulate end of file */
818 tok_add(&str
, &len
, 0);
819 /* now evaluate C constant expression */
829 void tok_print(int *str
)
840 printf(" %s", get_tok_str(t
, c
));
846 /* XXX: should be more factorized */
847 void define_symbol(char *sym
)
852 ts
= tok_alloc(sym
, 0);
855 tok_add2(&str
, &len
, TOK_NUM
, 1);
856 tok_add(&str
, &len
, 0);
857 sym_push1(&define_stack
, ts
->tok
, MACRO_OBJ
, (int)str
);
862 int size
, i
, c
, v
, t
, *str
, len
;
863 char buf
[1024], *q
, *p
;
866 Sym
**ps
, *first
, *s
;
871 if (tok
== TOK_DEFINE
) {
874 /* XXX: should check if same macro (ANSI) */
877 /* '(' must be just after macro definition for MACRO_FUNC */
884 tok
= TOK___VA_ARGS__
;
885 s
= sym_push1(&define_stack
, tok
| SYM_FIELD
, 0, 0);
899 if (ch
== '\n' || ch
== -1)
902 tok_add2(&str
, &len
, tok
, tokc
);
904 tok_add(&str
, &len
, 0);
906 printf("define %s %d: ", get_tok_str(v
, 0), t
);
909 s
= sym_push1(&define_stack
, v
, t
, (int)str
);
911 } else if (tok
== TOK_UNDEF
) {
913 s
= sym_find1(&define_stack
, tok
);
914 /* undefine symbol by putting an invalid name */
916 sym_undef(&define_stack
, s
);
917 } else if (tok
== TOK_INCLUDE
) {
922 } else if (ch
== '\"') {
927 while (ch
!= c
&& ch
!= '\n' && ch
!= -1) {
928 if ((q
- buf
) < sizeof(buf
) - 1)
936 error("#include syntax error");
937 /* XXX: buffer overflow */
938 strcpy(buf
, get_tok_str(tok
, tokc
));
941 if (include_stack_ptr
>= include_stack
+ INCLUDE_STACK_SIZE
)
942 error("memory full");
944 /* first search in current dir if "header.h" */
945 /* XXX: buffer overflow */
947 p
= strrchr(filename
, '/');
949 size
= p
+ 1 - filename
;
950 memcpy(buf1
, filename
, size
);
953 f
= fopen(buf1
, "r");
957 /* now search in standard include path */
958 for(i
=nb_include_paths
- 1;i
>=0;i
--) {
959 strcpy(buf1
, include_paths
[i
]);
962 f
= fopen(buf1
, "r");
966 error("include file '%s' not found", buf1
);
969 /* push current file in stack */
970 /* XXX: fix current line init */
971 include_stack_ptr
->file
= file
;
972 include_stack_ptr
->filename
= filename
;
973 include_stack_ptr
->line_num
= line_num
;
976 filename
= strdup(buf1
);
978 } else if (tok
== TOK_IFNDEF
) {
981 } else if (tok
== TOK_IF
) {
982 c
= expr_preprocess();
984 } else if (tok
== TOK_IFDEF
) {
988 c
= (sym_find1(&define_stack
, tok
) != 0) ^ c
;
990 if (ifdef_stack_ptr
>= ifdef_stack
+ IFDEF_STACK_SIZE
)
991 error("memory full");
992 *ifdef_stack_ptr
++ = c
;
994 } else if (tok
== TOK_ELSE
) {
995 if (ifdef_stack_ptr
== ifdef_stack
||
996 (ifdef_stack_ptr
[-1] & 2))
997 error("#else after #else");
998 c
= (ifdef_stack_ptr
[-1] ^= 3);
1000 } else if (tok
== TOK_ELIF
) {
1001 if (ifdef_stack_ptr
== ifdef_stack
||
1002 ifdef_stack_ptr
[-1] > 1)
1003 error("#elif after #else");
1004 c
= expr_preprocess();
1005 ifdef_stack_ptr
[-1] = c
;
1011 } else if (tok
== TOK_ENDIF
) {
1012 if (ifdef_stack_ptr
== ifdef_stack
)
1015 } else if (tok
== TOK_LINE
) {
1025 /* XXX: potential memory leak */
1026 filename
= strdup(get_tok_str(tok
, tokc
));
1028 } else if (tok
== TOK_ERROR
) {
1031 /* ignore other preprocess commands or #! for C scripts */
1032 while (ch
!= '\n' && ch
!= -1)
1036 /* read a number in base b */
1042 if (ch
>= 'a' & ch
<= 'f')
1044 else if (ch
>= 'A' & ch
<= 'F')
1058 /* read a character for string or char constant and eval escape codes */
1067 /* at most three octal digits */
1071 c
= c
* 8 + ch
- '0';
1074 c
= c
* 8 + ch
- '0';
1079 } else if (ch
== 'x') {
1097 else if (ch
== 'e' && gnu_ext
)
1099 else if (ch
== '\'' || ch
== '\"' || ch
== '\\')
1102 error("invalid escaped char");
1109 /* return next token without macro substitution */
1110 void next_nomacro1()
1118 while (ch
== '\n') {
1120 while (ch
== ' ' || ch
== 9)
1123 /* preprocessor command if # at start of line after
1128 if (ch
!= ' ' && ch
!= '\t' && ch
!= '\f')
1146 while (isid(ch
) || isnum(ch
)) {
1147 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1148 error("ident too long");
1153 ts
= tok_alloc(token_buf
, q
- token_buf
);
1155 } else if (isnum(ch
)) {
1161 if (ch
== 'x' || ch
== 'X') {
1164 } else if (ch
== 'b' || ch
== 'B') {
1170 /* XXX: add unsigned constant support (ANSI) */
1171 while (ch
== 'L' || ch
== 'l' || ch
== 'U' || ch
== 'u')
1174 } else if (ch
== '\'') {
1182 } else if (ch
== '\"') {
1187 while (ch
!= '\"') {
1190 error("unterminated string");
1191 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1192 error("string too long");
1196 tokc
= (int)tok_alloc(token_buf
, q
- token_buf
);
1199 q
= "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\247..\250##\266";
1204 if (*q
== tok
& q
[1] == ch
) {
1207 /* three chars tests */
1208 if (tok
== TOK_SHL
| tok
== TOK_SAR
) {
1213 } else if (tok
== TOK_DOTS
) {
1215 error("parse error");
1222 /* single char substitutions */
1225 else if (tok
== '>')
1230 /* return next token without macro substitution. Can read input from
1238 if (is_long_tok(tok
))
1239 tokc
= *macro_ptr
++;
1246 /* substitute args in macro_str and return allocated string */
1247 int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
1249 int *st
, last_tok
, t
, c
, notfirst
, *str
, len
;
1265 s
= sym_find2(args
, t
);
1267 token_buf
[0] = '\0';
1269 /* XXX: buffer overflow */
1273 strcat(token_buf
, " ");
1278 strcat(token_buf
, get_tok_str(t
, c
));
1282 printf("stringize: %s\n", token_buf
);
1285 ts
= tok_alloc(token_buf
, 0);
1286 tok_add2(&str
, &len
, TOK_STR
, (int)ts
);
1288 tok_add(&str
, &len
, t
);
1290 } else if (is_long_tok(t
)) {
1291 tok_add2(&str
, &len
, t
, *macro_str
++);
1293 s
= sym_find2(args
, t
);
1296 /* if '##' is present before or after , no arg substitution */
1297 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
1299 tok_add(&str
, &len
, *st
++);
1301 macro_subst(&str
, &len
, nested_list
, st
);
1304 tok_add(&str
, &len
, t
);
1309 tok_add(&str
, &len
, 0);
1313 /* handle the '##' operator */
1314 int *macro_twosharps(int *macro_str
)
1317 int *macro_str1
, macro_str1_len
, *macro_ptr1
;
1328 if (*macro_ptr
== TOK_TWOSHARPS
) {
1330 macro_ptr1
= macro_ptr
;
1337 /* XXX: we handle only most common cases:
1338 ident + ident or ident + number */
1339 if (tok
>= TOK_IDENT
&&
1340 (t
>= TOK_IDENT
|| t
== TOK_NUM
)) {
1341 /* XXX: buffer overflow */
1342 p
= get_tok_str(tok
, tokc
);
1343 strcpy(token_buf
, p
);
1344 p
= get_tok_str(t
, c
);
1345 strcat(token_buf
, p
);
1346 ts
= tok_alloc(token_buf
, 0);
1347 tok_add2(¯o_str1
, ¯o_str1_len
, ts
->tok
, 0);
1349 /* cannot merge tokens: skip '##' */
1350 macro_ptr
= macro_ptr1
;
1354 tok_add2(¯o_str1
, ¯o_str1_len
, tok
, tokc
);
1357 tok_add(¯o_str1
, ¯o_str1_len
, 0);
1363 /* do macro substitution of macro_str and add result to
1364 (tok_str,tok_len). If macro_str is NULL, then input stream token is
1365 substituted. 'nested_list' is the list of all macros we got inside
1366 to avoid recursing. */
1367 void macro_subst(int **tok_str
, int *tok_len
,
1368 Sym
**nested_list
, int *macro_str
)
1370 Sym
*s
, *args
, *sa
, *sa1
;
1371 int *str
, parlevel
, len
, *mstr
, t
, *saved_macro_ptr
;
1372 int mstr_allocated
, *macro_str1
;
1374 saved_macro_ptr
= macro_ptr
;
1375 macro_ptr
= macro_str
;
1378 /* first scan for '##' operator handling */
1379 macro_str1
= macro_twosharps(macro_str
);
1380 macro_ptr
= macro_str1
;
1387 /* special macros */
1388 if (tok
== TOK___LINE__
) {
1389 tok_add2(tok_str
, tok_len
, TOK_NUM
, line_num
);
1390 } else if (tok
== TOK___FILE__
) {
1391 tok_add2(tok_str
, tok_len
, TOK_STR
,
1392 (int)tok_alloc(filename
, 0));
1393 } else if (tok
== TOK___DATE__
) {
1394 tok_add2(tok_str
, tok_len
, TOK_STR
,
1395 (int)tok_alloc("Jan 1 1970", 0));
1396 } else if (tok
== TOK___TIME__
) {
1397 tok_add2(tok_str
, tok_len
, TOK_STR
,
1398 (int)tok_alloc("00:00:00", 0));
1399 } else if ((s
= sym_find1(&define_stack
, tok
)) != NULL
) {
1400 /* if symbol is a macro, prepare substitution */
1401 /* if nested substitution, do nothing */
1402 if (sym_find2(*nested_list
, tok
))
1406 if (s
->t
== MACRO_FUNC
) {
1407 /* NOTE: we do not use next_nomacro to avoid eating the
1408 next token. XXX: find better solution */
1412 while (ch
== ' ' || ch
== '\t' || ch
== '\n')
1416 if (t
!= '(') /* no macro subst */
1419 /* argument macro */
1424 while (tok
!= ')' && sa
) {
1428 while ((parlevel
> 0 ||
1431 sa
->v
== (TOK___VA_ARGS__
| SYM_FIELD
)))) &&
1435 else if (tok
== ')')
1437 tok_add2(&str
, &len
, tok
, tokc
);
1440 tok_add(&str
, &len
, 0);
1441 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, 0, (int)str
);
1449 /* now subst each arg */
1450 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
1461 sym_push2(nested_list
, s
->v
, 0, 0);
1462 macro_subst(tok_str
, tok_len
, nested_list
, mstr
);
1463 /* pop nested defined symbol */
1465 *nested_list
= sa1
->prev
;
1471 /* no need to add if reading input stream */
1474 tok_add2(tok_str
, tok_len
, tok
, tokc
);
1476 /* only replace one macro while parsing input stream */
1480 macro_ptr
= saved_macro_ptr
;
1485 /* return next token with macro substitution */
1491 /* special 'ungettok' case for label parsing */
1499 /* if not reading from macro substuted string, then try to substitute */
1503 macro_subst(&ptr
, &len
, &nested_list
, NULL
);
1505 tok_add(&ptr
, &len
, 0);
1507 macro_ptr_allocated
= ptr
;
1515 /* end of macro string: free it */
1516 free(macro_ptr_allocated
);
1523 printf("token = %s\n", get_tok_str(tok
, tokc
));
1527 void swap(int *p
, int *q
)
1535 void vset(int t
, int v
)
1541 #include "i386-gen.c"
1543 int save_reg_forced(int r
)
1547 /* store register */
1548 loc
= (loc
- 4) & -3;
1549 store(r
, VT_LOCAL
, loc
);
1552 /* modify all stack values */
1553 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1554 i
= p
[0] & VT_VALMASK
;
1560 p
[0] = (p
[0] & VT_TYPE
) | VT_LVAL
| t
;
1567 /* save r to memory. and mark it as being free */
1568 void save_reg(int r
)
1572 /* modify all stack values */
1573 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1574 i
= p
[0] & VT_VALMASK
;
1582 /* find a free register of class 'rc'. If none, save one register */
1587 /* find a free register */
1588 for(r
=0;r
<NB_REGS
;r
++) {
1589 if (reg_classes
[r
] & rc
) {
1590 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1591 i
= p
[0] & VT_VALMASK
;
1600 /* no register left : free the first one on the stack (very
1601 important to start from the bottom to ensure that we don't
1602 spill registers used in gen_op()) */
1603 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1604 r
= p
[0] & VT_VALMASK
;
1605 if (r
< VT_CONST
&& (reg_classes
[r
] & rc
)) {
1616 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1617 r
= p
[0] & VT_VALMASK
;
1624 /* move register 's' to 'r', and flush previous value of r to memory
1626 void move_reg(int r
, int s
)
1634 /* convert a (vt, vc) in register. lvalues are converted as
1635 values. Cannot be used if cannot be converted to register value
1636 (such as structures). */
1639 int r
, bit_pos
, bit_size
, rc
;
1641 /* NOTE: get_reg can modify vstack[] */
1642 if (vt
& VT_BITFIELD
) {
1643 bit_pos
= (vt
>> VT_STRUCT_SHIFT
) & 0x3f;
1644 bit_size
= (vt
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
1645 /* remove bit field info to avoid loops */
1646 vt
&= ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
1647 /* generate shifts */
1649 vset(VT_CONST
, 32 - (bit_pos
+ bit_size
));
1652 vset(VT_CONST
, 32 - bit_size
);
1653 /* NOTE: transformed to SHR if unsigned */
1657 r
= vt
& VT_VALMASK
;
1658 if (r
>= VT_CONST
|| (vt
& VT_LVAL
)) {
1659 if ((vt
& VT_BTYPE
) == VT_FLOAT
||
1660 (vt
& VT_BTYPE
) == VT_DOUBLE
)
1661 rc
= REG_CLASS_FLOAT
;
1667 vt
= (vt
& VT_TYPE
) | r
;
1674 if (vstack_ptr
>= vstack
+ VSTACK_SIZE
)
1675 error("memory full");
1676 /* cannot let cpu flags if other instruction are generated */
1677 /* XXX: VT_JMP test too ? */
1678 if ((vt
& VT_VALMASK
) == VT_CMP
)
1684 void vpop(int *ft
, int *fc
)
1686 *fc
= *--vstack_ptr
;
1687 *ft
= *--vstack_ptr
;
1692 swap(vstack_ptr
- 4, vstack_ptr
- 2);
1693 swap(vstack_ptr
- 3, vstack_ptr
- 1);
1696 /* generate a value in a register from vt and vc */
1700 vpush(); /* need so that gvp does not allocate the register we
1707 /* handle constant optimizations and various machine independant opt */
1708 void gen_opc(int op
)
1710 int fr
, ft
, fc
, r
, c1
, c2
, n
;
1714 /* currently, we cannot do computations with forward symbols */
1715 c1
= (vt
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
1716 c2
= (ft
& (VT_VALMASK
| VT_LVAL
| VT_FORWARD
)) == VT_CONST
;
1719 case '+': vc
+= fc
; break;
1720 case '-': vc
-= fc
; break;
1721 case '&': vc
&= fc
; break;
1722 case '^': vc
^= fc
; break;
1723 case '|': vc
|= fc
; break;
1724 case '*': vc
*= fc
; break;
1726 case '/': vc
/= fc
; break; /* XXX: zero case ? */
1727 case '%': vc
%= fc
; break; /* XXX: zero case ? */
1728 case TOK_UDIV
: vc
= (unsigned)vc
/ fc
; break; /* XXX: zero case ? */
1729 case TOK_UMOD
: vc
= (unsigned)vc
% fc
; break; /* XXX: zero case ? */
1730 case TOK_SHL
: vc
<<= fc
; break;
1731 case TOK_SHR
: vc
= (unsigned)vc
>> fc
; break;
1732 case TOK_SAR
: vc
>>= fc
; break;
1734 case TOK_ULT
: vc
= (unsigned)vc
< (unsigned)fc
; break;
1735 case TOK_UGE
: vc
= (unsigned)vc
>= (unsigned)fc
; break;
1736 case TOK_EQ
: vc
= vc
== fc
; break;
1737 case TOK_NE
: vc
= vc
!= fc
; break;
1738 case TOK_ULE
: vc
= (unsigned)vc
<= (unsigned)fc
; break;
1739 case TOK_UGT
: vc
= (unsigned)vc
> (unsigned)fc
; break;
1740 case TOK_LT
: vc
= vc
< fc
; break;
1741 case TOK_GE
: vc
= vc
>= fc
; break;
1742 case TOK_LE
: vc
= vc
<= fc
; break;
1743 case TOK_GT
: vc
= vc
> fc
; break;
1745 case TOK_LAND
: vc
= vc
&& fc
; break;
1746 case TOK_LOR
: vc
= vc
|| fc
; break;
1751 /* if commutative ops, put c2 as constant */
1752 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
1753 op
== '|' || op
== '*')) {
1758 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
1761 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
1762 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
1766 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
1767 /* try to use shifts instead of muls or divs */
1768 if (fc
> 0 && (fc
& (fc
- 1)) == 0) {
1777 else if (op
== TOK_PDIV
)
1789 fr
= gv(); /* second operand */
1794 r
= gv(); /* first operand */
1797 /* call low level op generator */
1803 int pointed_size(int t
)
1805 return type_size(pointed_type(t
), &t
);
1808 /* generic gen_op: handles types problems */
1811 int u
, t1
, t2
, bt1
, bt2
, t
;
1814 t1
= vstack_ptr
[-4];
1815 t2
= vstack_ptr
[-2];
1816 bt1
= t1
& VT_BTYPE
;
1817 bt2
= t2
& VT_BTYPE
;
1819 if (bt1
== VT_FLOAT
|| bt1
== VT_DOUBLE
||
1820 bt2
== VT_FLOAT
|| bt2
== VT_DOUBLE
) {
1821 /* compute bigger type and do implicit casts */
1822 if (bt1
!= VT_DOUBLE
&& bt2
!= VT_DOUBLE
) {
1827 if (op
!= '+' && op
!= '-' && op
!= '*' && op
!= '/' &&
1828 op
< TOK_EQ
|| op
> TOK_GT
)
1829 error("invalid operands for binary operation");
1843 if (op
>= TOK_EQ
&& op
<= TOK_GT
) {
1844 /* the result is an int */
1845 vt
= (vt
& ~VT_TYPE
) | VT_INT
;
1847 vt
= (vt
& ~VT_TYPE
) | t
;
1849 } else if (op
== '+' | op
== '-') {
1850 if ((t1
& VT_BTYPE
) == VT_PTR
&&
1851 (t2
& VT_BTYPE
) == VT_PTR
) {
1853 error("invalid type");
1854 /* XXX: check that types are compatible */
1855 u
= pointed_size(t1
);
1858 vstack_ptr
[-2] &= ~VT_TYPE
; /* set to integer */
1861 } else if ((t1
& VT_BTYPE
) == VT_PTR
||
1862 (t2
& VT_BTYPE
) == VT_PTR
) {
1863 if ((t2
& VT_BTYPE
) == VT_PTR
) {
1864 swap(vstack_ptr
- 4, vstack_ptr
- 2);
1865 swap(vstack_ptr
- 3, vstack_ptr
- 1);
1868 /* stack-4 contains pointer, stack-2 value to add */
1869 vset(VT_CONST
, pointed_size(vstack_ptr
[-4]));
1873 /* put again type if gen_opc() swaped operands */
1874 vt
= (vt
& ~VT_TYPE
) | (t1
& VT_TYPE
);
1879 /* XXX: test types and compute returned value */
1880 if ((t1
| t2
) & VT_UNSIGNED
||
1881 (t1
& VT_BTYPE
) == VT_PTR
||
1882 (t2
& VT_BTYPE
) == VT_PTR
) {
1889 else if (op
== TOK_LT
)
1891 else if (op
== TOK_GT
)
1893 else if (op
== TOK_LE
)
1895 else if (op
== TOK_GE
)
1902 /* cast (vt, vc) to 't' type */
1903 void gen_cast(int t
)
1907 r
= vt
& VT_VALMASK
;
1908 if (!(t
& VT_LVAL
)) {
1909 /* if not lvalue, then we convert now */
1911 if (bt
== VT_FLOAT
|| bt
== VT_DOUBLE
) {
1912 if ((vt
& VT_BTYPE
) != bt
) {
1913 /* need to generate value and do explicit cast */
1918 } else if (bt
== VT_BOOL
) {
1923 } else if (bt
== VT_BYTE
)
1925 else if (bt
== VT_SHORT
)
1930 if (t
& VT_UNSIGNED
) {
1931 vset(VT_CONST
, (1 << bits
) - 1);
1935 vset(VT_CONST
, bits
);
1938 vset(VT_CONST
, bits
);
1943 vt
= (vt
& ~VT_TYPE
) | t
;
1946 /* return type size. Put alignment at 'a' */
1947 int type_size(int t
, int *a
)
1953 if (bt
== VT_STRUCT
) {
1955 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
1956 *a
= 4; /* XXX: cannot store it yet. Doing that is safe */
1958 } else if (bt
== VT_PTR
) {
1960 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
1961 return type_size(s
->t
, a
) * s
->c
;
1966 } else if (bt
== VT_DOUBLE
) {
1969 } else if (bt
== VT_INT
|| bt
== VT_ENUM
|| bt
== VT_FLOAT
) {
1972 } else if (bt
== VT_SHORT
) {
1976 /* char, void, function, _Bool */
1982 /* return the pointed type of t */
1983 int pointed_type(int t
)
1986 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
1987 return s
->t
| (t
& ~VT_TYPE
);
1990 int mk_pointer(int t
)
1995 return VT_PTR
| (p
<< VT_STRUCT_SHIFT
) | (t
& ~VT_TYPE
);
1998 /* store value in lvalue pushed on stack */
2001 int ft
, fc
, r
, t
, size
, align
, bit_size
, bit_pos
;
2004 if ((vt
& VT_BTYPE
) == VT_STRUCT
) {
2005 /* if structure, only generate pointer */
2006 /* structure assignment : generate memcpy */
2007 /* XXX: optimize if small size */
2013 size
= type_size(vt
, &align
);
2014 vset(VT_CONST
, size
);
2026 vset(VT_CONST
, (int)&memcpy
);
2029 /* generate again current type */
2032 } else if (vstack_ptr
[-2] & VT_BITFIELD
) {
2033 /* bitfield store handling */
2034 ft
= vstack_ptr
[-2];
2035 bit_pos
= (ft
>> VT_STRUCT_SHIFT
) & 0x3f;
2036 bit_size
= (ft
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f;
2037 /* remove bit field info to avoid loops */
2038 vstack_ptr
[-2] = ft
& ~(VT_BITFIELD
| (-1 << VT_STRUCT_SHIFT
));
2040 /* mask and shift source */
2042 vset(VT_CONST
, (1 << bit_size
) - 1);
2045 vset(VT_CONST
, bit_pos
);
2048 /* load destination, mask and or with source */
2049 vt
= vstack_ptr
[-4];
2050 vc
= vstack_ptr
[-3];
2052 vset(VT_CONST
, ~(((1 << bit_size
) - 1) << bit_pos
));
2058 if ((vstack_ptr
[-2] & VT_BTYPE
) == VT_BOOL
) {
2059 /* implicit cast for bool */
2062 r
= gv(); /* generate value */
2064 ft
= vstack_ptr
[-4];
2065 fc
= vstack_ptr
[-3];
2066 /* if lvalue was saved on stack, must read it */
2067 if ((ft
& VT_VALMASK
) == VT_LLOCAL
) {
2068 t
= get_reg(REG_CLASS_INT
);
2069 load(t
, VT_LOCAL
| VT_LVAL
, fc
);
2070 ft
= (ft
& ~VT_VALMASK
) | t
;
2077 /* post defines POST/PRE add. c is the token ++ or -- */
2078 void inc(int post
, int c
)
2083 vpush(); /* room for returned value */
2084 vpush(); /* save lvalue */
2086 vpush(); /* save value */
2088 /* duplicate value */
2089 /* XXX: handle floats */
2090 r1
= get_reg(REG_CLASS_INT
);
2091 load(r1
, r
, 0); /* move r to r1 */
2092 vstack_ptr
[-6] = (vt
& VT_TYPE
) | r1
;
2096 vset(VT_CONST
, c
- TOK_MID
);
2098 vstore(); /* store value */
2103 /* enum/struct/union declaration */
2104 int struct_decl(int u
)
2106 int a
, t
, b
, v
, size
, align
, maxalign
, c
, offset
;
2107 int bit_size
, bit_pos
, bsize
, bt
, lbit_pos
;
2110 a
= tok
; /* save decl type */
2115 /* struct already defined ? return it */
2116 /* XXX: check consistency */
2117 if (s
= sym_find(v
| SYM_STRUCT
)) {
2119 error("invalid type");
2125 s
= sym_push(v
| SYM_STRUCT
, a
, 0);
2126 /* put struct/union/enum name in type */
2128 u
= u
| (v
<< VT_STRUCT_SHIFT
);
2133 error("struct/union/enum already defined");
2134 /* cannot be empty */
2141 if (a
== TOK_ENUM
) {
2148 /* enum symbols have static storage */
2149 sym_push(v
, VT_CONST
| VT_STATIC
, c
);
2159 t
= type_decl(&v
, b
, TYPE_DIRECT
);
2160 if ((t
& VT_BTYPE
) == VT_FUNC
||
2161 (t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
)))
2162 error("invalid type for '%s'", get_tok_str(v
, 0));
2168 bit_size
= expr_const();
2169 /* XXX: handle v = 0 case for messages */
2171 error("negative width in bit-field '%s'",
2173 if (v
&& bit_size
== 0)
2174 error("zero width for bit-field '%s'",
2177 size
= type_size(t
, &align
);
2179 if (bit_size
>= 0) {
2184 error("bitfields must have scalar type");
2186 if (bit_size
> bsize
) {
2187 error("width of '%s' exceeds its type",
2189 } else if (bit_size
== bsize
) {
2190 /* no need for bit fields */
2192 } else if (bit_size
== 0) {
2193 /* XXX: what to do if only padding in a
2195 /* zero size: means to pad */
2199 /* we do not have enough room ? */
2200 if ((bit_pos
+ bit_size
) > bsize
)
2203 /* XXX: handle LSB first */
2205 (bit_pos
<< VT_STRUCT_SHIFT
) |
2206 (bit_size
<< (VT_STRUCT_SHIFT
+ 6));
2207 bit_pos
+= bit_size
;
2213 /* add new memory data only if starting
2215 if (lbit_pos
== 0) {
2216 if (a
== TOK_STRUCT
) {
2217 c
= (c
+ align
- 1) & -align
;
2225 if (align
> maxalign
)
2229 printf("add field %s offset=%d",
2230 get_tok_str(v
, 0), offset
);
2231 if (t
& VT_BITFIELD
) {
2232 printf(" pos=%d size=%d",
2233 (t
>> VT_STRUCT_SHIFT
) & 0x3f,
2234 (t
>> (VT_STRUCT_SHIFT
+ 6)) & 0x3f);
2238 ss
= sym_push(v
| SYM_FIELD
, t
, offset
);
2242 if (tok
== ';' || tok
== -1)
2252 /* size for struct/union, dummy for enum */
2253 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
2258 /* return 0 if no type declaration. otherwise, return the basic type
2260 XXX: A '2' is ored to ensure non zero return if int type.
2276 if ((t
& VT_BTYPE
) != 0)
2277 error("too many basic types %x", t
);
2290 /* XXX: add long type */
2303 u
= struct_decl(VT_ENUM
);
2307 u
= struct_decl(VT_STRUCT
);
2310 /* type modifiers */
2340 if (!s
|| !(s
->t
& VT_TYPEDEF
))
2342 t
|= (s
->t
& ~VT_TYPEDEF
);
2352 int post_type(int t
)
2354 int p
, n
, pt
, l
, t1
;
2355 Sym
**plast
, *s
, *first
;
2358 /* function declaration */
2363 while (tok
!= ')') {
2364 /* read param name and compute offset */
2365 if (l
!= FUNC_OLD
) {
2366 if (!(pt
= ist())) {
2368 error("invalid type");
2374 if ((pt
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
2377 pt
= type_decl(&n
, pt
, TYPE_DIRECT
| TYPE_ABSTRACT
);
2384 /* array must be transformed to pointer according to ANSI C */
2386 s
= sym_push(n
| SYM_FIELD
, pt
, 0);
2391 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
2399 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
2400 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
));
2401 /* we push a anonymous symbol which will contain the function prototype */
2403 s
= sym_push(p
, t
, l
);
2405 t
= t1
| VT_FUNC
| (p
<< VT_STRUCT_SHIFT
);
2406 } else if (tok
== '[') {
2407 /* array definition */
2413 error("invalid array size");
2416 /* parse next post type */
2417 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
2418 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
));
2420 /* we push a anonymous symbol which will contain the array
2424 t
= t1
| VT_ARRAY
| VT_PTR
| (p
<< VT_STRUCT_SHIFT
);
2429 /* Read a type declaration (except basic type), and return the
2430 type. If v is true, then also put variable name in 'vc' */
2431 int type_decl(int *v
, int t
, int td
)
2436 t
= t
& -3; /* suppress the ored '2' */
2437 while (tok
== '*') {
2439 while (tok
== TOK_CONST
|| tok
== TOK_VOLATILE
|| tok
== TOK_RESTRICT
)
2444 /* recursive type */
2445 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
2448 u
= type_decl(v
, 0, td
);
2452 /* type identifier */
2453 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
2457 if (!(td
& TYPE_ABSTRACT
))
2458 expect("identifier");
2462 /* append t at the end of u */
2468 s
= sym_find((unsigned)p
>> VT_STRUCT_SHIFT
);
2478 /* define a new external reference to a function 'v' of type 'u' */
2479 Sym
*external_sym(int v
, int u
)
2484 /* push forward reference */
2485 s
= sym_push1(&global_stack
,
2486 v
, u
| VT_CONST
| VT_FORWARD
, 0);
2495 if ((vt
& VT_BTYPE
) != VT_PTR
)
2497 vt
= pointed_type(vt
);
2498 if (!(vt
& VT_ARRAY
)) /* an array is never an lvalue */
2504 int n
, t
, ft
, fc
, p
, align
, size
;
2508 if (tok
== TOK_NUM
|| tok
== TOK_CCHAR
|| tok
== TOK_LCHAR
) {
2509 vset(VT_CONST
, tokc
);
2511 } else if (tok
== TOK___FUNC__
) {
2512 /* special function name identifier */
2513 /* generate (char *) type */
2514 vset(VT_CONST
| mk_pointer(VT_BYTE
), glo
);
2515 strcpy((void *)glo
, funcname
);
2516 glo
+= strlen(funcname
) + 1;
2518 } else if (tok
== TOK_LSTR
) {
2521 } else if (tok
== TOK_STR
) {
2522 /* string parsing */
2525 type_size(t
, &align
);
2526 glo
= (glo
+ align
- 1) & -align
;
2528 /* we must declare it as an array first to use initializer parser */
2529 t
= VT_CONST
| VT_ARRAY
| mk_pointer(t
);
2530 decl_initializer(t
, glo
, 1, 0);
2531 glo
+= type_size(t
, &align
);
2532 /* put it as pointer */
2533 vset(t
& ~VT_ARRAY
, fc
);
2540 ft
= type_decl(&n
, t
, TYPE_ABSTRACT
);
2542 /* check ISOC99 compound literal */
2544 /* data is allocated locally by default */
2549 /* all except arrays are lvalues */
2550 if (!(ft
& VT_ARRAY
))
2552 fc
= decl_initializer_alloc(ft
, 1);
2562 } else if (t
== '*') {
2565 } else if (t
== '&') {
2567 /* functions names must be treated as function pointers,
2568 except for unary '&' and sizeof. Since we consider that
2569 functions are not lvalues, we only have to handle it
2570 there and in function calls. */
2571 if ((vt
& VT_BTYPE
) != VT_FUNC
)
2573 vt
= mk_pointer(vt
& VT_LVALN
);
2577 if ((vt
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
)
2579 else if ((vt
& VT_VALMASK
) == VT_CMP
)
2582 vset(VT_JMP
, gtst(1, 0));
2593 if (t
== TOK_SIZEOF
) {
2594 /* XXX: some code can be generated */
2598 vt
= type_decl(&n
, t
, TYPE_ABSTRACT
);
2605 vset(VT_CONST
, type_size(vt
, &t
));
2607 if (t
== TOK_INC
| t
== TOK_DEC
) {
2610 } else if (t
== '-') {
2620 error("'%s' undeclared", get_tok_str(t
, 0));
2621 /* for simple function calls, we tolerate undeclared
2622 external reference */
2624 sym_push1(&global_stack
, p
, 0, FUNC_OLD
);
2625 /* int() function */
2626 s
= external_sym(t
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
));
2629 /* if forward reference, we must point to s */
2630 if (vt
& VT_FORWARD
)
2635 /* post operations */
2637 if (tok
== TOK_INC
| tok
== TOK_DEC
) {
2640 } else if (tok
== '.' | tok
== TOK_ARROW
) {
2642 if (tok
== TOK_ARROW
)
2647 /* expect pointer on structure */
2648 if ((vt
& VT_BTYPE
) != VT_STRUCT
)
2649 expect("struct or union");
2650 s
= sym_find(((unsigned)vt
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
2653 while (s
= s
->next
) {
2658 error("field not found");
2659 /* add field offset to pointer */
2660 vt
= (vt
& ~VT_TYPE
) | VT_INT
; /* change type to int */
2662 vset(VT_CONST
, s
->c
);
2664 /* change type to field type, and set to lvalue */
2665 vt
= (vt
& ~VT_TYPE
) | s
->t
;
2666 /* an array is never an lvalue */
2667 if (!(vt
& VT_ARRAY
))
2670 } else if (tok
== '[') {
2677 } else if (tok
== '(') {
2681 if ((vt
& VT_BTYPE
) != VT_FUNC
) {
2682 /* pointer test (no array accepted) */
2683 if ((vt
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
2684 vt
= pointed_type(vt
);
2685 if ((vt
& VT_BTYPE
) != VT_FUNC
)
2689 expect("function pointer");
2692 vt
&= ~VT_LVAL
; /* no lvalue */
2695 /* get return type */
2696 s
= sym_find((unsigned)vt
>> VT_STRUCT_SHIFT
);
2697 vpush(); /* push function address */
2698 save_regs(); /* save used temporary registers */
2701 #ifdef INVERT_FUNC_PARAMS
2703 int *str
, len
, parlevel
, *saved_macro_ptr
;
2706 /* read each argument and store it on a stack */
2707 /* XXX: merge it with macro args ? */
2709 while (tok
!= ')') {
2713 while ((parlevel
> 0 || (tok
!= ')' && tok
!= ',')) &&
2717 else if (tok
== ')')
2719 tok_add2(&str
, &len
, tok
, tokc
);
2722 tok_add(&str
, &len
, -1); /* end of file added */
2723 tok_add(&str
, &len
, 0);
2724 sym_push2(&args
, 0, 0, (int)str
);
2732 /* now generate code in reverse order by reading the stack */
2733 saved_macro_ptr
= macro_ptr
;
2735 macro_ptr
= (int *)args
->c
;
2739 expect("',' or ')'");
2742 free((int *)args
->c
);
2746 macro_ptr
= saved_macro_ptr
;
2751 /* compute first implicit argument if a structure is returned */
2752 if ((s
->t
& VT_BTYPE
) == VT_STRUCT
) {
2753 /* get some space for the returned structure */
2754 size
= type_size(s
->t
, &align
);
2755 loc
= (loc
- size
) & -align
;
2756 rett
= s
->t
| VT_LOCAL
| VT_LVAL
;
2757 /* pass it as 'int' to avoid structure arg passing
2759 vset(VT_INT
| VT_LOCAL
, loc
);
2763 rett
= s
->t
| FUNC_RET_REG
; /* return in register */
2766 #ifndef INVERT_FUNC_PARAMS
2767 while (tok
!= ')') {
2786 int is_compatible_types(int t1
, int t2
)
2793 bt1
= t1
& VT_BTYPE
;
2794 bt2
= t2
& VT_BTYPE
;
2795 if (bt1
== VT_PTR
) {
2796 t1
= pointed_type(t1
);
2797 /* if function, then convert implictely to function pointer */
2798 if (bt2
!= VT_FUNC
) {
2801 t2
= pointed_type(t2
);
2803 /* void matches everything */
2806 if (t1
== VT_VOID
|| t2
== VT_VOID
)
2808 return is_compatible_types(t1
, t2
);
2809 } else if (bt1
== VT_STRUCT
) {
2811 } else if (bt1
== VT_FUNC
) {
2814 s1
= sym_find(((unsigned)t1
>> VT_STRUCT_SHIFT
));
2815 s2
= sym_find(((unsigned)t2
>> VT_STRUCT_SHIFT
));
2816 if (!is_compatible_types(s1
->t
, s2
->t
))
2818 /* XXX: not complete */
2819 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
2823 while (s1
!= NULL
) {
2826 if (!is_compatible_types(s1
->t
, s2
->t
))
2835 /* XXX: not complete */
2840 int check_assign_types(int t1
, int t2
)
2844 if ((t1
& VT_BTYPE
) == VT_PTR
&&
2845 (t2
& VT_BTYPE
) == VT_FUNC
) {
2846 return is_compatible_types(pointed_type(t1
), t2
);
2848 return is_compatible_types(t1
, t2
);
2859 (tok
>= TOK_A_MOD
&& tok
<= TOK_A_DIV
) ||
2860 tok
== TOK_A_XOR
|| tok
== TOK_A_OR
||
2861 tok
== TOK_A_SHL
|| tok
== TOK_A_SAR
) {
2868 if (!check_assign_types(vstack_ptr
[-2], vt
))
2869 warning("incompatible types");
2887 while ((l
== 0 & (tok
== '*' | tok
== '/' | tok
== '%')) |
2888 (l
== 1 & (tok
== '+' | tok
== '-')) |
2889 (l
== 2 & (tok
== TOK_SHL
| tok
== TOK_SAR
)) |
2890 (l
== 3 & ((tok
>= TOK_ULE
& tok
<= TOK_GT
) |
2891 tok
== TOK_ULT
| tok
== TOK_UGE
)) |
2892 (l
== 4 & (tok
== TOK_EQ
| tok
== TOK_NE
)) |
2893 (l
== 5 & tok
== '&') |
2894 (l
== 6 & tok
== '^') |
2895 (l
== 7 & tok
== '|') |
2896 (l
== 8 & tok
== TOK_LAND
) |
2897 (l
== 9 & tok
== TOK_LOR
)) {
2907 /* only used if non constant */
2915 if (tok
!= TOK_LAND
) {
2935 if (tok
!= TOK_LOR
) {
2948 /* XXX: better constant handling */
2951 int t
, u
, c
, r1
, r2
;
2978 vt
= (vt
& VT_TYPE
) | r1
;
3000 if ((vt
& (VT_CONST
| VT_LVAL
)) != VT_CONST
)
3006 /* return the label token if current token is a label, otherwise
3012 /* fast test first */
3013 if (tok
< TOK_UIDENT
)
3022 /* XXX: may not work in all cases (macros ?) */
3031 void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
, int case_reg
)
3036 if (tok
== TOK_IF
) {
3043 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3045 if (c
== TOK_ELSE
) {
3049 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3050 gsym(d
); /* patch else jmp */
3053 } else if (tok
== TOK_WHILE
) {
3061 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
3062 oad(0xe9, d
- ind
- 5); /* jmp */
3065 } else if (tok
== '{') {
3068 s
= local_stack
.top
;
3069 while (tok
!= '}') {
3072 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3074 /* pop locally defined symbols */
3075 sym_pop(&local_stack
, s
);
3077 } else if (tok
== TOK_RETURN
) {
3080 if ((func_vt
& VT_BTYPE
) == VT_STRUCT
) {
3081 /* if returning structure, must copy it to implicit
3082 first pointer arg location */
3083 vset(mk_pointer(func_vt
) | VT_LOCAL
| VT_LVAL
, func_vc
);
3088 if ((func_vt
& VT_BTYPE
) == VT_STRUCT
) {
3089 /* copy structure value to pointer */
3092 /* move return value to standard return register */
3093 move_reg(FUNC_RET_REG
, gv());
3097 rsym
= gjmp(rsym
); /* jmp */
3098 } else if (tok
== TOK_BREAK
) {
3101 error("cannot break");
3102 *bsym
= gjmp(*bsym
);
3105 } else if (tok
== TOK_CONTINUE
) {
3108 error("cannot continue");
3109 *csym
= gjmp(*csym
);
3112 } else if (tok
== TOK_FOR
) {
3132 oad(0xe9, d
- ind
- 5); /* jmp */
3136 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
3137 oad(0xe9, c
- ind
- 5); /* jmp */
3141 if (tok
== TOK_DO
) {
3146 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
3157 if (tok
== TOK_SWITCH
) {
3164 b
= gjmp(0); /* jump to first case */
3166 block(&a
, csym
, &b
, &c
, case_reg
);
3167 /* if no default, jmp after switch */
3175 if (tok
== TOK_CASE
) {
3180 /* since a case is like a label, we must skip it with a jmp */
3187 *case_sym
= gtst(1, 0);
3190 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3192 if (tok
== TOK_DEFAULT
) {
3198 error("too many 'default'");
3200 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3202 if (tok
== TOK_GOTO
) {
3204 s
= sym_find1(&label_stack
, tok
);
3205 /* put forward definition if needed */
3207 s
= sym_push1(&label_stack
, tok
, VT_FORWARD
, 0);
3208 /* label already defined */
3209 if (s
->t
& VT_FORWARD
)
3210 s
->c
= gjmp(s
->c
); /* jmp xxx */
3212 oad(0xe9, s
->c
- ind
- 5); /* jmp xxx */
3219 s
= sym_find1(&label_stack
, b
);
3221 if (!(s
->t
& VT_FORWARD
))
3222 error("multiple defined label");
3227 sym_push1(&label_stack
, b
, 0, ind
);
3229 /* we accept this, but it is a mistake */
3231 warning("deprecated use of label at end of compound statement");
3233 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3235 /* expression case */
3244 /* t is the array or struct type. c is the array or struct
3245 address. cur_index/cur_field is the pointer to the current
3246 value. 'size_only' is true if only size info is needed (only used
3248 void decl_designator(int t
, int c
,
3249 int *cur_index
, Sym
**cur_field
,
3253 int notfirst
, index
, align
, l
;
3256 if (gnu_ext
&& (l
= is_label()) != 0)
3259 while (tok
== '[' || tok
== '.') {
3261 if (!(t
& VT_ARRAY
))
3262 expect("array type");
3263 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3265 index
= expr_const();
3266 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
3267 expect("invalid index");
3271 t
= pointed_type(t
);
3272 c
+= index
* type_size(t
, &align
);
3278 if ((t
& VT_BTYPE
) != VT_STRUCT
)
3279 expect("struct/union type");
3280 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
3292 t
= f
->t
| (t
& ~VT_TYPE
);
3307 t
= pointed_type(t
);
3308 c
+= index
* type_size(t
, &align
);
3312 error("too many field init");
3313 t
= f
->t
| (t
& ~VT_TYPE
);
3317 decl_initializer(t
, c
, 0, size_only
);
3320 /* store a value or an expression directly in global data or in local array */
3322 void init_putv(int t
, int c
, int v
, int is_expr
)
3324 int saved_global_expr
;
3326 if ((t
& VT_VALMASK
) == VT_CONST
) {
3328 /* compound literals must be allocated globally in this case */
3329 saved_global_expr
= global_expr
;
3332 global_expr
= saved_global_expr
;
3334 if ((t
& VT_BTYPE
) == VT_BYTE
)
3336 else if ((t
& VT_BTYPE
) == VT_SHORT
)
3352 /* put zeros for variable based init */
3353 void init_putz(int t
, int c
, int size
)
3357 if ((t
& VT_VALMASK
) == VT_CONST
) {
3358 /* nothing to do because global are already set to zero */
3361 vset(VT_CONST
, size
);
3367 vset(VT_CONST
, (int)&memset
);
3372 /* 't' contains the type and storage info. c is the address of the
3373 object. 'first' is true if array '{' must be read (multi dimension
3374 implicit array init handling). 'size_only' is true if size only
3375 evaluation is wanted (only for arrays). */
3376 void decl_initializer(int t
, int c
, int first
, int size_only
)
3378 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
3379 int t1
, size1
, align1
;
3384 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3387 t1
= pointed_type(t
);
3388 size1
= type_size(t1
, &align1
);
3391 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
3397 /* only parse strings here if correct type (otherwise: handle
3398 them as ((w)char *) expressions */
3399 if ((tok
== TOK_LSTR
&&
3400 (t1
& VT_BTYPE
) == VT_INT
) ||
3402 (t1
& VT_BTYPE
) == VT_BYTE
)) {
3403 /* XXX: move multiple string parsing in parser ? */
3404 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
3405 ts
= (TokenSym
*)tokc
;
3406 /* compute maximum number of chars wanted */
3408 if (n
>= 0 && nb
> (n
- array_length
))
3409 nb
= n
- array_length
;
3412 warning("initializer-string for array is too long");
3414 init_putv(t1
, c
+ (array_length
+ i
) * size1
,
3421 /* only add trailing zero if enough storage (no
3422 warning in this case since it is standard) */
3423 if (n
< 0 || array_length
< n
) {
3425 init_putv(t1
, c
+ (array_length
* size1
), 0, 0);
3431 while (tok
!= '}') {
3432 decl_designator(t
, c
, &index
, NULL
, size_only
);
3433 if (n
>= 0 && index
>= n
)
3434 error("index too large");
3435 /* must put zero in holes (note that doing it that way
3436 ensures that it even works with designators) */
3437 if (!size_only
&& array_length
< index
) {
3438 init_putz(t1
, c
+ array_length
* size1
,
3439 (index
- array_length
) * size1
);
3442 if (index
> array_length
)
3443 array_length
= index
;
3444 /* special test for multi dimensional arrays (may not
3445 be strictly correct if designators are used at the
3447 if (index
>= n
&& no_oblock
)
3456 /* put zeros at the end */
3457 if (!size_only
&& n
>= 0 && array_length
< n
) {
3458 init_putz(t1
, c
+ array_length
* size1
,
3459 (n
- array_length
) * size1
);
3461 /* patch type size if needed */
3463 s
->c
= array_length
;
3464 } else if ((t
& VT_BTYPE
) == VT_STRUCT
&& tok
== '{') {
3465 /* XXX: union needs only one init */
3467 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
3472 while (tok
!= '}') {
3473 decl_designator(t
, c
, NULL
, &f
, size_only
);
3474 /* fill with zero between fields */
3476 if (!size_only
&& array_length
< index
) {
3477 init_putz(t
, c
+ array_length
,
3478 index
- array_length
);
3480 index
= index
+ type_size(f
->t
, &align1
);
3481 if (index
> array_length
)
3482 array_length
= index
;
3488 /* put zeros at the end */
3489 if (!size_only
&& array_length
< n
) {
3490 init_putz(t
, c
+ array_length
,
3494 } else if (tok
== '{') {
3496 decl_initializer(t
, c
, first
, size_only
);
3498 } else if (size_only
) {
3499 /* just skip expression */
3501 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
3505 else if (tok
== ')')
3510 init_putv(t
, c
, 0, 1);
3514 /* parse an initializer for type 't' if 'has_init' is true, and
3515 allocate space in local or global data space. The allocated address
3517 int decl_initializer_alloc(int t
, int has_init
)
3519 int size
, align
, addr
, tok1
;
3520 int *init_str
, init_len
, level
, *saved_macro_ptr
;
3522 size
= type_size(t
, &align
);
3523 /* If unknown size, we must evaluate it before
3524 evaluating initializers because
3525 initializers can generate global data too
3526 (e.g. string pointers or ISOC99 compound
3527 literals). It also simplifies local
3528 initializers handling */
3531 saved_macro_ptr
= NULL
; /* avoid warning */
3535 error("unknown type size");
3536 /* get all init string */
3538 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
3540 error("unexpect end of file in initializer");
3541 tok_add2(&init_str
, &init_len
, tok
, tokc
);
3544 else if (tok
== '}') {
3552 tok_add(&init_str
, &init_len
, -1);
3553 tok_add(&init_str
, &init_len
, 0);
3556 saved_macro_ptr
= macro_ptr
;
3557 macro_ptr
= init_str
;
3559 decl_initializer(t
, 0, 1, 1);
3560 /* prepare second initializer parsing */
3561 macro_ptr
= init_str
;
3564 /* if still unknown size, error */
3565 size
= type_size(t
, &align
);
3567 error("unknown type size");
3569 if ((t
& VT_VALMASK
) == VT_LOCAL
) {
3570 loc
= (loc
- size
) & -align
;
3573 glo
= (glo
+ align
- 1) & -align
;
3575 /* very important to increment global
3576 pointer at this time because
3577 initializers themselves can create new
3582 decl_initializer(t
, addr
, 1, 0);
3583 /* restore parse state if needed */
3586 macro_ptr
= saved_macro_ptr
;
3594 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
3597 int *a
, t
, b
, v
, u
, addr
, has_init
, size
, align
;
3603 /* skip redundant ';' */
3604 /* XXX: find more elegant solution */
3609 /* special test for old K&R protos without explicit int
3610 type. Only accepted when defining global data */
3611 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
3615 if (((b
& VT_BTYPE
) == VT_ENUM
||
3616 (b
& VT_BTYPE
) == VT_STRUCT
) &&
3618 /* we accept no variable after */
3622 while (1) { /* iterate thru each declaration */
3623 t
= type_decl(&v
, b
, TYPE_DIRECT
);
3626 error("cannot use local functions");
3628 expect("function definition");
3629 /* patch forward references */
3630 if ((sym
= sym_find(v
)) && (sym
->t
& VT_FORWARD
)) {
3631 greloc_patch(sym
, ind
);
3632 sym
->t
= VT_CONST
| t
;
3634 /* put function address */
3635 sym_push1(&global_stack
, v
, VT_CONST
| t
, ind
);
3637 funcname
= get_tok_str(v
, 0);
3638 /* push a dummy symbol to enable local sym storage */
3639 sym_push1(&local_stack
, 0, 0, 0);
3640 /* define parameters */
3641 sym
= sym_find((unsigned)t
>> VT_STRUCT_SHIFT
);
3642 /* XXX: the following is x86 dependant -> move it to
3645 /* if the function returns a structure, then add an
3646 implicit pointer parameter */
3648 if ((func_vt
& VT_BTYPE
) == VT_STRUCT
) {
3652 while (sym
= sym
->next
) {
3654 sym_push(sym
->v
& ~SYM_FIELD
,
3655 u
| VT_LOCAL
| VT_LVAL
,
3657 if ((u
& VT_BTYPE
) == VT_STRUCT
) {
3658 #ifdef FUNC_STRUCT_PARAM_AS_PTR
3659 /* structs are passed as pointer */
3662 /* structs are directly put on stack (x86
3664 size
= type_size(u
, &align
);
3665 size
= (size
+ 3) & ~3;
3668 /* XXX: size will be different someday */
3674 o(0xe58955); /* push %ebp, mov %esp, %ebp */
3675 a
= (int *)oad(0xec81, 0); /* sub $xxx, %esp */
3677 block(0, 0, 0, 0, 0);
3679 o(0xc3c9); /* leave, ret */
3680 *a
= (-loc
+ 3) & -4; /* align local size to word &
3681 save local variables */
3682 sym_pop(&label_stack
, NULL
); /* reset label stack */
3683 sym_pop(&local_stack
, NULL
); /* reset local stack */
3684 funcname
= ""; /* for safety */
3685 func_vt
= VT_VOID
; /* for safety */
3688 if (b
& VT_TYPEDEF
) {
3689 /* save typedefed type */
3690 /* XXX: test storage specifiers ? */
3691 sym_push(v
, t
| VT_TYPEDEF
, 0);
3692 } else if ((t
& VT_BTYPE
) == VT_FUNC
) {
3693 /* external function definition */
3696 /* not lvalue if array */
3697 if (!(t
& VT_ARRAY
))
3699 if (b
& VT_EXTERN
) {
3700 /* external variable */
3707 has_init
= (tok
== '=');
3710 addr
= decl_initializer_alloc(u
, has_init
);
3711 if (l
== VT_CONST
) {
3712 /* global scope: see if already defined */
3716 if (!is_compatible_types(sym
->t
, u
))
3717 error("incompatible types for redefinition of '%s'",
3719 if (!(sym
->t
& VT_FORWARD
))
3720 error("redefinition of '%s'", get_tok_str(v
, 0));
3721 greloc_patch(sym
, addr
);
3724 sym_push(v
, u
, addr
);
3738 /* put all global symbols in the extern stack and do all the
3739 resolving which can be done without using external symbols from DLLs */
3740 /* XXX: could try to verify types, but would not to save them in
3742 void resolve_global_syms(void)
3744 Sym
*s
, *s1
, *ext_sym
;
3747 s
= global_stack
.top
;
3750 /* do not save static or typedefed symbols or types */
3751 if (!(s
->t
& (VT_STATIC
| VT_TYPEDEF
)) &&
3752 !(s
->v
& (SYM_FIELD
| SYM_STRUCT
)) &&
3753 (s
->v
< SYM_FIRST_ANOM
)) {
3754 ext_sym
= sym_find1(&extern_stack
, s
->v
);
3756 /* if the symbol do not exist, we simply save it */
3757 sym_push1(&extern_stack
, s
->v
, s
->t
, s
->c
);
3758 } else if (ext_sym
->t
& VT_FORWARD
) {
3759 /* external symbol already exists, but only as forward
3761 if (!(s
->t
& VT_FORWARD
)) {
3762 /* s is not forward, so we can relocate all symbols */
3763 greloc_patch(ext_sym
, s
->c
);
3765 /* the two symbols are forward: merge them */
3766 p
= (Reloc
**)&ext_sym
->c
;
3772 /* external symbol already exists and is defined :
3773 patch all references to it */
3774 if (!(s
->t
& VT_FORWARD
))
3775 error("'%s' defined twice", get_tok_str(s
->v
, 0));
3776 greloc_patch(s
, ext_sym
->c
);
3783 /* compile a C file. Return non zero if errors. */
3784 int tcc_compile_file(const char *filename1
)
3788 filename
= (char *)filename1
;
3792 file
= fopen(filename
, "r");
3794 error("file '%s' not found", filename
);
3795 include_stack_ptr
= include_stack
;
3796 ifdef_stack_ptr
= ifdef_stack
;
3798 vstack_ptr
= vstack
;
3799 anon_sym
= SYM_FIRST_ANOM
;
3801 define_start
= define_stack
.top
;
3803 ch
= '\n'; /* needed to parse correctly first preprocessor command */
3807 expect("declaration");
3810 /* reset define stack, but leave -Dsymbols (may be incorrect if
3811 they are undefined) */
3812 sym_pop(&define_stack
, define_start
);
3814 resolve_global_syms();
3816 sym_pop(&global_stack
, NULL
);
3821 /* open a dynamic library so that its symbol are available for
3822 compiled programs */
3823 void open_dll(char *libname
)
3828 snprintf(buf
, sizeof(buf
), "lib%s.so", libname
);
3829 h
= dlopen(buf
, RTLD_GLOBAL
| RTLD_LAZY
);
3831 error((char *)dlerror());
3834 void resolve_extern_syms(void)
3840 s
= extern_stack
.top
;
3843 if (s
->t
& VT_FORWARD
) {
3844 /* if there is at least one relocation to do, then find it
3847 str
= get_tok_str(s
->v
, 0);
3848 addr
= (int)dlsym(NULL
, str
);
3850 error("unresolved external reference '%s'", str
);
3851 greloc_patch(s
, addr
);
3858 /* output a binary file (for testing) */
3859 void build_exe(char *filename
)
3862 f
= fopen(filename
, "w");
3863 fwrite((void *)prog
, 1, ind
- prog
, f
);
3867 int main(int argc
, char **argv
)
3871 char *p
, *r
, *outfile
;
3874 include_paths
[0] = "/usr/include";
3875 include_paths
[1] = "/usr/lib/tcc";
3876 include_paths
[2] = "/usr/local/lib/tcc";
3877 nb_include_paths
= 3;
3879 /* add all tokens */
3880 tok_ident
= TOK_IDENT
;
3881 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";
3885 tok_alloc(p
, r
- p
- 1);
3889 /* standard defines */
3890 define_symbol("__STDC__");
3892 define_symbol("__i386__");
3894 /* tiny C specific defines */
3895 define_symbol("__TINYC__");
3897 glo
= (int)malloc(DATA_SIZE
);
3898 memset((void *)glo
, 0, DATA_SIZE
);
3899 prog
= (int)malloc(TEXT_SIZE
);
3905 if (optind
>= argc
) {
3907 printf("tcc version 0.9.2 - Tiny C Compiler - Copyright (C) 2001 Fabrice Bellard\n"
3908 "usage: tcc [-Idir] [-Dsym] [-llib] [-i infile] infile [infile_args...]\n");
3916 if (nb_include_paths
>= INCLUDE_PATHS_MAX
)
3917 error("too many include paths");
3918 include_paths
[nb_include_paths
++] = r
+ 2;
3919 } else if (r
[1] == 'D') {
3920 define_symbol(r
+ 2);
3921 } else if (r
[1] == 'l') {
3923 } else if (r
[1] == 'i') {
3926 tcc_compile_file(argv
[optind
++]);
3927 } else if (r
[1] == 'o') {
3928 /* currently, only for testing, so not documented */
3931 outfile
= argv
[optind
++];
3933 fprintf(stderr
, "invalid option -- '%s'\n", r
);
3938 tcc_compile_file(argv
[optind
]);
3940 resolve_extern_syms();
3946 s
= sym_find1(&extern_stack
, TOK_MAIN
);
3947 if (!s
|| (s
->t
& VT_FORWARD
))
3948 error("main() not defined");
3949 t
= (int (*)())s
->c
;
3950 return (*t
)(argc
- optind
, argv
+ optind
);