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) */
162 #define VT_EXTERN 0x00000040 /* extern definition */
163 #define VT_STATIC 0x00000080 /* static variable */
164 #define VT_TYPEDEF 0x00000100 /* typedef definition */
167 #define VT_STRUCT_SHIFT 15 /* structure/enum name shift (14 bits left) */
169 #define VT_BTYPE_SHIFT 9
170 #define VT_INT (0 << VT_BTYPE_SHIFT) /* integer type */
171 #define VT_BYTE (1 << VT_BTYPE_SHIFT) /* signed byte type */
172 #define VT_SHORT (2 << VT_BTYPE_SHIFT) /* short type */
173 #define VT_VOID (3 << VT_BTYPE_SHIFT) /* void type */
174 #define VT_PTR (4 << VT_BTYPE_SHIFT) /* pointer increment */
175 #define VT_ENUM (5 << VT_BTYPE_SHIFT) /* enum definition */
176 #define VT_FUNC (6 << VT_BTYPE_SHIFT) /* function type */
177 #define VT_STRUCT (7 << VT_BTYPE_SHIFT) /* struct/union definition */
178 #define VT_BTYPE (0xf << VT_BTYPE_SHIFT) /* mask for basic type */
179 #define VT_UNSIGNED (0x10 << VT_BTYPE_SHIFT) /* unsigned type */
180 #define VT_ARRAY (0x20 << VT_BTYPE_SHIFT) /* array type (also has VT_PTR) */
182 #define VT_TYPE 0xfffffe00 /* type mask */
186 /* warning: the following compare tokens depend on i386 asm code */
198 #define TOK_LAND 0xa0
202 #define TOK_MID 0xa3 /* inc/dec, to void constant */
204 #define TOK_ARROW 0xa7
205 #define TOK_DOTS 0xa8 /* three dots */
206 #define TOK_SHR 0xa9 /* unsigned shift right */
207 #define TOK_UDIV 0xb0 /* unsigned division */
208 #define TOK_UMOD 0xb1 /* unsigned modulo */
209 #define TOK_PDIV 0xb2 /* fast division with undefined rounding for pointers */
210 #define TOK_NUM 0xb3 /* number in tokc */
211 #define TOK_CCHAR 0xb4 /* char constant in tokc */
212 #define TOK_STR 0xb5 /* pointer to string in tokc */
213 #define TOK_TWOSHARPS 0xb6 /* ## preprocessing token */
214 #define TOK_LCHAR 0xb7
215 #define TOK_LSTR 0xb8
217 #define TOK_SHL 0x01 /* shift left */
218 #define TOK_SAR 0x02 /* signed shift right */
220 /* assignement operators : normal operator or 0x80 */
221 #define TOK_A_MOD 0xa5
222 #define TOK_A_AND 0xa6
223 #define TOK_A_MUL 0xaa
224 #define TOK_A_ADD 0xab
225 #define TOK_A_SUB 0xad
226 #define TOK_A_DIV 0xaf
227 #define TOK_A_XOR 0xde
228 #define TOK_A_OR 0xfc
229 #define TOK_A_SHL 0x81
230 #define TOK_A_SAR 0x82
232 /* all identificators and strings have token above that */
233 #define TOK_IDENT 256
254 /* ignored types Must have contiguous values */
264 /* unsupported type */
276 /* preprocessor only */
277 TOK_UIDENT
, /* first "user" ident (not keyword) */
278 TOK_DEFINE
= TOK_UIDENT
,
294 /* special identifiers */
306 void decl_initializer(int t
, int c
, int first
, int size_only
);
307 int decl_initializer_alloc(int t
, int has_init
);
313 void macro_subst(int **tok_str
, int *tok_len
,
314 Sym
**nested_list
, int *macro_str
);
315 int save_reg_forced(int r
);
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
);
446 /* expand token table if needed */
447 i
= tok_ident
- TOK_IDENT
;
448 if ((i
% TOK_ALLOC_INCR
) == 0) {
449 ptable
= realloc(table_ident
, (i
+ TOK_ALLOC_INCR
) * sizeof(TokenSym
*));
451 error("memory full");
452 table_ident
= ptable
;
454 ts
= malloc(sizeof(TokenSym
) + len
);
455 if (!ts
|| tok_ident
>= SYM_FIRST_ANOM
)
456 error("memory full");
458 ts
->tok
= tok_ident
++;
460 ts
->hash_next
= NULL
;
461 memcpy(ts
->str
, str
, len
+ 1);
466 void add_char(char **pp
, int c
)
470 if (c
== '\'' || c
== '\"' || c
== '\\') {
471 /* XXX: could be more precise if char or string */
474 if (c
>= 32 && c
<= 126) {
481 *p
++ = '0' + ((c
>> 6) & 7);
482 *p
++ = '0' + ((c
>> 3) & 7);
483 *p
++ = '0' + (c
& 7);
489 /* XXX: buffer overflow */
490 char *get_tok_str(int v
, int c
)
492 static char buf
[STRING_MAX_SIZE
+ 1];
498 sprintf(buf
, "%d", c
);
500 } else if (v
== TOK_CCHAR
|| v
== TOK_LCHAR
) {
507 } else if (v
== TOK_STR
|| v
== TOK_LSTR
) {
511 for(i
=0;i
<ts
->len
;i
++)
512 add_char(&p
, ts
->str
[i
]);
516 } else if (v
< TOK_IDENT
) {
521 } else if (v
< tok_ident
) {
522 return table_ident
[v
- TOK_IDENT
]->str
;
524 /* should never happen */
529 /* push, without hashing */
530 Sym
*sym_push2(Sym
**ps
, int v
, int t
, int c
)
533 s
= malloc(sizeof(Sym
));
535 error("memory full");
546 /* find a symbol and return its associated structure. 's' is the top
547 of the symbol stack */
548 Sym
*sym_find2(Sym
*s
, int v
)
558 /* find a symbol and return its associated structure. 'st' is the
560 Sym
*sym_find1(SymStack
*st
, int v
)
564 s
= st
->hash
[v
% SYM_HASH_SIZE
];
573 Sym
*sym_push1(SymStack
*st
, int v
, int t
, int c
)
576 s
= sym_push2(&st
->top
, v
, t
, c
);
577 /* add in hash table */
578 ps
= &st
->hash
[s
->v
% SYM_HASH_SIZE
];
584 /* find a symbol in the right symbol space */
588 s
= sym_find1(&local_stack
, v
);
590 s
= sym_find1(&global_stack
, v
);
594 /* push a given symbol on the symbol stack */
595 Sym
*sym_push(int v
, int t
, int c
)
598 return sym_push1(&local_stack
, v
, t
, c
);
600 return sym_push1(&global_stack
, v
, t
, c
);
603 /* pop symbols until top reaches 'b' */
604 void sym_pop(SymStack
*st
, Sym
*b
)
611 /* free hash table entry */
612 st
->hash
[s
->v
% SYM_HASH_SIZE
] = s
->hash_next
;
619 /* undefined a hashed symbol (used for #undef). Its name is set to
621 void sym_undef(SymStack
*st
, Sym
*s
)
624 ss
= &st
->hash
[s
->v
% SYM_HASH_SIZE
];
625 while (*ss
!= NULL
) {
628 ss
= &(*ss
)->hash_next
;
634 /* no need to put that inline */
637 if (include_stack_ptr
== include_stack
)
639 /* pop include stack */
643 file
= include_stack_ptr
->file
;
644 filename
= include_stack_ptr
->filename
;
645 line_num
= include_stack_ptr
->line_num
;
649 /* read next char from current input file */
650 static inline void inp(void)
653 /* faster than fgetc */
654 ch1
= getc_unlocked(file
);
656 if (handle_eof() < 0)
663 // printf("ch1=%c 0x%x\n", ch1, ch1);
666 /* input with '\\n' handling */
667 static inline void minp(void)
672 if (ch
== '\\' && ch1
== '\n') {
676 //printf("ch=%c 0x%x\n", ch, ch);
680 /* same as minp, but also skip comments */
688 /* single line C++ comments */
690 while (ch1
!= '\n' && ch1
!= -1)
693 ch
= ' '; /* return space */
694 } else if (ch1
== '*') {
700 if (c
== '*' && ch1
== '/') {
702 ch
= ' '; /* return space */
714 void skip_spaces(void)
716 while (ch
== ' ' || ch
== '\t')
720 /* skip block of text until #else, #elif or #endif. skip also pairs of
722 void preprocess_skip()
738 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
740 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
742 else if (tok
== TOK_ENDIF
)
748 inline int is_long_tok(int t
)
750 return (t
== TOK_NUM
||
751 t
== TOK_CCHAR
|| t
== TOK_LCHAR
||
752 t
== TOK_STR
|| t
== TOK_LSTR
);
755 void tok_add(int **tok_str
, int *tok_len
, int t
)
760 if ((len
& 63) == 0) {
761 str
= realloc(str
, (len
+ 64) * sizeof(int));
770 void tok_add2(int **tok_str
, int *tok_len
, int t
, int c
)
772 tok_add(tok_str
, tok_len
, t
);
774 tok_add(tok_str
, tok_len
, c
);
777 /* eval an expression for #if/#elif */
778 int expr_preprocess()
788 next(); /* do macro subst */
789 if (tok
== TOK_DEFINED
) {
794 c
= sym_find1(&define_stack
, tok
) != 0;
799 } else if (tok
>= TOK_IDENT
) {
800 /* if undefined macro */
804 tok_add2(&str
, &len
, tok
, tokc
);
806 tok_add(&str
, &len
, -1); /* simulate end of file */
807 tok_add(&str
, &len
, 0);
808 /* now evaluate C constant expression */
818 void tok_print(int *str
)
829 printf(" %s", get_tok_str(t
, c
));
835 /* XXX: should be more factorized */
836 void define_symbol(char *sym
)
841 ts
= tok_alloc(sym
, 0);
844 tok_add2(&str
, &len
, TOK_NUM
, 1);
845 tok_add(&str
, &len
, 0);
846 sym_push1(&define_stack
, ts
->tok
, MACRO_OBJ
, (int)str
);
851 int size
, i
, c
, v
, t
, *str
, len
;
852 char buf
[1024], *q
, *p
;
855 Sym
**ps
, *first
, *s
;
860 if (tok
== TOK_DEFINE
) {
863 /* XXX: should check if same macro (ANSI) */
866 /* '(' must be just after macro definition for MACRO_FUNC */
873 tok
= TOK___VA_ARGS__
;
874 s
= sym_push1(&define_stack
, tok
| SYM_FIELD
, 0, 0);
888 if (ch
== '\n' || ch
== -1)
891 tok_add2(&str
, &len
, tok
, tokc
);
893 tok_add(&str
, &len
, 0);
895 printf("define %s %d: ", get_tok_str(v
, 0), t
);
898 s
= sym_push1(&define_stack
, v
, t
, (int)str
);
900 } else if (tok
== TOK_UNDEF
) {
902 s
= sym_find1(&define_stack
, tok
);
903 /* undefine symbol by putting an invalid name */
905 sym_undef(&define_stack
, s
);
906 } else if (tok
== TOK_INCLUDE
) {
911 } else if (ch
== '\"') {
916 while (ch
!= c
&& ch
!= '\n' && ch
!= -1) {
917 if ((q
- buf
) < sizeof(buf
) - 1)
925 error("#include syntax error");
926 /* XXX: buffer overflow */
927 strcpy(buf
, get_tok_str(tok
, tokc
));
930 if (include_stack_ptr
>= include_stack
+ INCLUDE_STACK_SIZE
)
931 error("memory full");
933 /* first search in current dir if "header.h" */
934 /* XXX: buffer overflow */
936 p
= strrchr(filename
, '/');
938 size
= p
+ 1 - filename
;
939 memcpy(buf1
, filename
, size
);
942 f
= fopen(buf1
, "r");
946 /* now search in standard include path */
947 for(i
=nb_include_paths
- 1;i
>=0;i
--) {
948 strcpy(buf1
, include_paths
[i
]);
951 f
= fopen(buf1
, "r");
955 error("include file '%s' not found", buf1
);
958 /* push current file in stack */
959 /* XXX: fix current line init */
960 include_stack_ptr
->file
= file
;
961 include_stack_ptr
->filename
= filename
;
962 include_stack_ptr
->line_num
= line_num
;
965 filename
= strdup(buf1
);
967 } else if (tok
== TOK_IFNDEF
) {
970 } else if (tok
== TOK_IF
) {
971 c
= expr_preprocess();
973 } else if (tok
== TOK_IFDEF
) {
977 c
= (sym_find1(&define_stack
, tok
) != 0) ^ c
;
979 if (ifdef_stack_ptr
>= ifdef_stack
+ IFDEF_STACK_SIZE
)
980 error("memory full");
981 *ifdef_stack_ptr
++ = c
;
983 } else if (tok
== TOK_ELSE
) {
984 if (ifdef_stack_ptr
== ifdef_stack
||
985 (ifdef_stack_ptr
[-1] & 2))
986 error("#else after #else");
987 c
= (ifdef_stack_ptr
[-1] ^= 3);
989 } else if (tok
== TOK_ELIF
) {
990 if (ifdef_stack_ptr
== ifdef_stack
||
991 ifdef_stack_ptr
[-1] > 1)
992 error("#elif after #else");
993 c
= expr_preprocess();
994 ifdef_stack_ptr
[-1] = c
;
1000 } else if (tok
== TOK_ENDIF
) {
1001 if (ifdef_stack_ptr
== ifdef_stack
)
1004 } else if (tok
== TOK_LINE
) {
1014 /* XXX: potential memory leak */
1015 filename
= strdup(get_tok_str(tok
, tokc
));
1017 } else if (tok
== TOK_ERROR
) {
1020 /* ignore other preprocess commands or #! for C scripts */
1021 while (ch
!= '\n' && ch
!= -1)
1025 /* read a number in base b */
1031 if (ch
>= 'a' & ch
<= 'f')
1033 else if (ch
>= 'A' & ch
<= 'F')
1047 /* read a character for string or char constant and eval escape codes */
1056 /* at most three octal digits */
1060 c
= c
* 8 + ch
- '0';
1063 c
= c
* 8 + ch
- '0';
1068 } else if (ch
== 'x') {
1094 /* return next token without macro substitution */
1095 void next_nomacro1()
1103 while (ch
== '\n') {
1105 while (ch
== ' ' || ch
== 9)
1108 /* preprocessor command if # at start of line after
1113 if (ch
!= ' ' && ch
!= '\t' && ch
!= '\f')
1131 while (isid(ch
) | isnum(ch
)) {
1132 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1133 error("ident too long");
1138 ts
= tok_alloc(token_buf
, q
- token_buf
);
1140 } else if (isnum(ch
)) {
1146 if (ch
== 'x' || ch
== 'X') {
1149 } else if (ch
== 'b' || ch
== 'B') {
1155 /* XXX: add unsigned constant support (ANSI) */
1156 while (ch
== 'L' || ch
== 'l' || ch
== 'U' || ch
== 'u')
1159 } else if (ch
== '\'') {
1167 } else if (ch
== '\"') {
1172 while (ch
!= '\"') {
1175 error("unterminated string");
1176 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1177 error("string too long");
1181 tokc
= (int)tok_alloc(token_buf
, q
- token_buf
);
1184 q
= "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\247..\250##\266";
1189 if (*q
== tok
& q
[1] == ch
) {
1192 /* three chars tests */
1193 if (tok
== TOK_SHL
| tok
== TOK_SAR
) {
1198 } else if (tok
== TOK_DOTS
) {
1200 error("parse error");
1207 /* single char substitutions */
1210 else if (tok
== '>')
1215 /* return next token without macro substitution. Can read input from
1223 if (is_long_tok(tok
))
1224 tokc
= *macro_ptr
++;
1231 /* substitute args in macro_str and return allocated string */
1232 int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
1234 int *st
, last_tok
, t
, c
, notfirst
, *str
, len
;
1250 s
= sym_find2(args
, t
);
1252 token_buf
[0] = '\0';
1254 /* XXX: buffer overflow */
1258 strcat(token_buf
, " ");
1263 strcat(token_buf
, get_tok_str(t
, c
));
1267 printf("stringize: %s\n", token_buf
);
1270 ts
= tok_alloc(token_buf
, 0);
1271 tok_add2(&str
, &len
, TOK_STR
, (int)ts
);
1273 tok_add(&str
, &len
, t
);
1275 } else if (is_long_tok(t
)) {
1276 tok_add2(&str
, &len
, t
, *macro_str
++);
1278 s
= sym_find2(args
, t
);
1281 /* if '##' is present before or after , no arg substitution */
1282 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
1284 tok_add(&str
, &len
, *st
++);
1286 macro_subst(&str
, &len
, nested_list
, st
);
1289 tok_add(&str
, &len
, t
);
1294 tok_add(&str
, &len
, 0);
1298 /* handle the '##' operator */
1299 int *macro_twosharps(int *macro_str
)
1302 int *macro_str1
, macro_str1_len
, *macro_ptr1
;
1313 if (*macro_ptr
== TOK_TWOSHARPS
) {
1315 macro_ptr1
= macro_ptr
;
1322 /* XXX: we handle only most common cases:
1323 ident + ident or ident + number */
1324 if (tok
>= TOK_IDENT
&&
1325 (t
>= TOK_IDENT
|| t
== TOK_NUM
)) {
1326 /* XXX: buffer overflow */
1327 p
= get_tok_str(tok
, tokc
);
1328 strcpy(token_buf
, p
);
1329 p
= get_tok_str(t
, c
);
1330 strcat(token_buf
, p
);
1331 ts
= tok_alloc(token_buf
, 0);
1332 tok_add2(¯o_str1
, ¯o_str1_len
, ts
->tok
, 0);
1334 /* cannot merge tokens: skip '##' */
1335 macro_ptr
= macro_ptr1
;
1339 tok_add2(¯o_str1
, ¯o_str1_len
, tok
, tokc
);
1342 tok_add(¯o_str1
, ¯o_str1_len
, 0);
1348 /* do macro substitution of macro_str and add result to
1349 (tok_str,tok_len). If macro_str is NULL, then input stream token is
1350 substituted. 'nested_list' is the list of all macros we got inside
1351 to avoid recursing. */
1352 void macro_subst(int **tok_str
, int *tok_len
,
1353 Sym
**nested_list
, int *macro_str
)
1355 Sym
*s
, *args
, *sa
, *sa1
;
1356 int *str
, parlevel
, len
, *mstr
, t
, *saved_macro_ptr
;
1357 int mstr_allocated
, *macro_str1
;
1359 saved_macro_ptr
= macro_ptr
;
1360 macro_ptr
= macro_str
;
1363 /* first scan for '##' operator handling */
1364 macro_str1
= macro_twosharps(macro_str
);
1365 macro_ptr
= macro_str1
;
1372 /* special macros */
1373 if (tok
== TOK___LINE__
) {
1374 tok_add2(tok_str
, tok_len
, TOK_NUM
, line_num
);
1375 } else if (tok
== TOK___FILE__
) {
1376 tok_add2(tok_str
, tok_len
, TOK_STR
,
1377 (int)tok_alloc(filename
, 0));
1378 } else if (tok
== TOK___DATE__
) {
1379 tok_add2(tok_str
, tok_len
, TOK_STR
,
1380 (int)tok_alloc("Jan 1 1970", 0));
1381 } else if (tok
== TOK___TIME__
) {
1382 tok_add2(tok_str
, tok_len
, TOK_STR
,
1383 (int)tok_alloc("00:00:00", 0));
1384 } else if ((s
= sym_find1(&define_stack
, tok
)) != NULL
) {
1385 /* if symbol is a macro, prepare substitution */
1386 /* if nested substitution, do nothing */
1387 if (sym_find2(*nested_list
, tok
))
1391 if (s
->t
== MACRO_FUNC
) {
1392 /* NOTE: we do not use next_nomacro to avoid eating the
1393 next token. XXX: find better solution */
1397 while (ch
== ' ' || ch
== '\t' || ch
== '\n')
1401 if (t
!= '(') /* no macro subst */
1404 /* argument macro */
1409 while (tok
!= ')' && sa
) {
1413 while ((parlevel
> 0 ||
1416 sa
->v
== (TOK___VA_ARGS__
| SYM_FIELD
)))) &&
1420 else if (tok
== ')')
1422 tok_add2(&str
, &len
, tok
, tokc
);
1425 tok_add(&str
, &len
, 0);
1426 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, 0, (int)str
);
1434 /* now subst each arg */
1435 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
1446 sym_push2(nested_list
, s
->v
, 0, 0);
1447 macro_subst(tok_str
, tok_len
, nested_list
, mstr
);
1448 /* pop nested defined symbol */
1450 *nested_list
= sa1
->prev
;
1456 /* no need to add if reading input stream */
1459 tok_add2(tok_str
, tok_len
, tok
, tokc
);
1461 /* only replace one macro while parsing input stream */
1465 macro_ptr
= saved_macro_ptr
;
1470 /* return next token with macro substitution */
1476 /* special 'ungettok' case for label parsing */
1484 /* if not reading from macro substuted string, then try to substitute */
1488 macro_subst(&ptr
, &len
, &nested_list
, NULL
);
1490 tok_add(&ptr
, &len
, 0);
1492 macro_ptr_allocated
= ptr
;
1500 /* end of macro string: free it */
1501 free(macro_ptr_allocated
);
1508 printf("token = %s\n", get_tok_str(tok
, tokc
));
1512 void swap(int *p
, int *q
)
1526 /******************************************************/
1527 /* X86 code generator */
1529 typedef struct GFuncContext
{
1546 void gen_le32(int c
)
1554 /* add a new relocation entry to symbol 's' */
1555 void greloc(Sym
*s
, int addr
, int type
)
1558 p
= malloc(sizeof(Reloc
));
1560 error("memory full");
1563 p
->next
= (Reloc
*)s
->c
;
1567 /* patch each relocation entry with value 'val' */
1568 void greloc_patch(Sym
*s
, int val
)
1577 *(int *)p
->addr
= val
;
1580 *(int *)p
->addr
= val
- p
->addr
- 4;
1587 s
->t
&= ~VT_FORWARD
;
1590 /* output a symbol and patch all calls to it */
1591 void gsym_addr(t
, a
)
1595 n
= *(int *)t
; /* next value */
1596 *(int *)t
= a
- t
- 4;
1606 /* psym is used to put an instruction with a data field which is a
1607 reference to a symbol. It is in fact the same as oad ! */
1610 /* instruction + 4 bytes data. Return the address of the data */
1611 int oad(int c
, int s
)
1620 /* output constant with relocation if 't & VT_FORWARD' is true */
1621 void gen_addr32(int c
, int t
)
1623 if (!(t
& VT_FORWARD
)) {
1626 greloc((Sym
*)c
, ind
, RELOC_ADDR32
);
1631 /* XXX: generate correct pointer for forward references to functions */
1633 void load(r
, ft
, fc
)
1637 v
= ft
& VT_VALMASK
;
1639 if (v
== VT_LLOCAL
) {
1640 load(r
, VT_LOCAL
| VT_LVAL
, fc
);
1643 if ((ft
& VT_TYPE
) == VT_BYTE
)
1644 o(0xbe0f); /* movsbl */
1645 else if ((ft
& VT_TYPE
) == (VT_BYTE
| VT_UNSIGNED
))
1646 o(0xb60f); /* movzbl */
1647 else if ((ft
& VT_TYPE
) == VT_SHORT
)
1648 o(0xbf0f); /* movswl */
1649 else if ((ft
& VT_TYPE
) == (VT_SHORT
| VT_UNSIGNED
))
1650 o(0xb70f); /* movzwl */
1653 if (v
== VT_CONST
) {
1654 o(0x05 + r
* 8); /* 0xXX, r */
1656 } else if (v
== VT_LOCAL
) {
1657 oad(0x85 + r
* 8, fc
); /* xx(%ebp), r */
1659 g(0x00 + r
* 8 + v
); /* (v), r */
1662 if (v
== VT_CONST
) {
1663 o(0xb8 + r
); /* mov $xx, r */
1665 } else if (v
== VT_LOCAL
) {
1667 oad(0x85 + r
* 8, fc
); /* lea xxx(%ebp), r */
1668 } else if (v
== VT_CMP
) {
1669 oad(0xb8 + r
, 0); /* mov $0, r */
1670 o(0x0f); /* setxx %br */
1673 } else if (v
== VT_JMP
|| v
== VT_JMPI
) {
1675 oad(0xb8 + r
, t
); /* mov $1, r */
1676 oad(0xe9, 5); /* jmp after */
1678 oad(0xb8 + r
, t
^ 1); /* mov $0, r */
1679 } else if (v
!= r
) {
1681 o(0xc0 + r
+ v
* 8); /* mov v, r */
1687 /* WARNING: r must not be allocated on the stack */
1688 void store(r
, ft
, fc
)
1692 fr
= ft
& VT_VALMASK
;
1694 /* XXX: incorrect if reg to reg */
1701 if (fr
== VT_CONST
) {
1702 o(0x05 + r
* 8); /* mov r,xxx */
1704 } else if (fr
== VT_LOCAL
) {
1705 oad(0x85 + r
* 8, fc
); /* mov r,xxx(%ebp) */
1706 } else if (ft
& VT_LVAL
) {
1707 g(fr
+ r
* 8); /* mov r, (fr) */
1708 } else if (fr
!= r
) {
1709 o(0xc0 + fr
+ r
* 8); /* mov r, fr */
1713 /* start function call and return function call context */
1714 void gfunc_start(GFuncContext
*c
)
1719 /* push function parameter which is in (vt, vc) */
1720 void gfunc_param(GFuncContext
*c
)
1722 int size
, align
, ft
, fc
, r
;
1724 if ((vt
& (VT_BTYPE
| VT_LVAL
)) == (VT_STRUCT
| VT_LVAL
)) {
1725 size
= type_size(vt
, &align
);
1726 /* align to stack align size */
1727 size
= (size
+ 3) & ~3;
1728 /* allocate the necessary size on stack */
1729 oad(0xec81, size
); /* sub $xxx, %esp */
1730 /* generate structure store */
1732 o(0x89); /* mov %esp, r */
1736 vset(VT_INT
| r
, 0);
1741 c
->args_size
+= size
;
1743 /* simple type (currently always same size) */
1744 /* XXX: implicit cast ? */
1746 o(0x50 + r
); /* push r */
1751 /* generate function call with address in (vt, vc) and free function
1753 void gfunc_call(GFuncContext
*c
)
1756 if ((vt
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
1758 /* forward reference */
1759 if (vt
& VT_FORWARD
) {
1760 greloc((Sym
*)vc
, ind
+ 1, RELOC_REL32
);
1763 oad(0xe8, vc
- ind
- 5);
1766 /* otherwise, indirect call */
1768 o(0xff); /* call *r */
1772 oad(0xc481, c
->args_size
); /* add $xxx, %esp */
1777 return psym(0xe9, t
);
1780 /* generate a test. set 'inv' to invert test */
1781 int gtst(int inv
, int t
)
1784 v
= vt
& VT_VALMASK
;
1786 /* fast case : can jump directly since flags are set */
1788 t
= psym((vc
- 16) ^ inv
, t
);
1789 } else if (v
== VT_JMP
|| v
== VT_JMPI
) {
1790 /* && or || optimization */
1791 if ((v
& 1) == inv
) {
1792 /* insert vc jump list in t */
1802 } else if ((vt
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
1803 /* constant jmp optimization */
1804 if ((vc
!= 0) != inv
)
1811 t
= psym(0x85 ^ inv
, t
);
1816 /* generate a binary operation 'v = r op fr' instruction and modifies
1817 (vt,vc) if needed */
1818 void gen_op1(int op
, int r
, int fr
)
1823 o(0xc0 + r
+ fr
* 8);
1824 } else if (op
== '-') {
1826 o(0xc0 + r
+ fr
* 8);
1827 } else if (op
== '&') {
1829 o(0xc0 + r
+ fr
* 8);
1830 } else if (op
== '^') {
1832 o(0xc0 + r
+ fr
* 8);
1833 } else if (op
== '|') {
1835 o(0xc0 + r
+ fr
* 8);
1836 } else if (op
== '*') {
1837 o(0xaf0f); /* imul fr, r */
1838 o(0xc0 + fr
+ r
* 8);
1839 } else if (op
== TOK_SHL
| op
== TOK_SHR
| op
== TOK_SAR
) {
1845 o(0x87); /* xchg r, %ecx */
1850 o(0xd3); /* shl/shr/sar %cl, r */
1853 else if (op
== TOK_SHR
)
1857 vt
= (vt
& VT_TYPE
) | r
;
1858 } else if (op
== '/' | op
== TOK_UDIV
| op
== TOK_PDIV
|
1859 op
== '%' | op
== TOK_UMOD
) {
1860 save_reg(2); /* save edx */
1861 t
= save_reg_forced(fr
); /* save fr and get op2 location */
1862 move_reg(0, r
); /* op1 is %eax */
1863 if (op
== TOK_UDIV
| op
== TOK_UMOD
) {
1864 o(0xf7d231); /* xor %edx, %edx, div t(%ebp), %eax */
1867 o(0xf799); /* cltd, idiv t(%ebp), %eax */
1870 if (op
== '%' | op
== TOK_UMOD
)
1874 vt
= (vt
& VT_TYPE
) | r
;
1877 o(0xc0 + r
+ fr
* 8); /* cmp fr, r */
1882 /* end of X86 code generator */
1883 /*************************************************************/
1885 int save_reg_forced(int r
)
1888 /* store register */
1889 loc
= (loc
- 4) & -3;
1890 store(r
, VT_LOCAL
, loc
);
1893 /* modify all stack values */
1894 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1895 i
= p
[0] & VT_VALMASK
;
1901 p
[0] = (p
[0] & VT_TYPE
) | VT_LVAL
| t
;
1908 /* save r to memory. and mark it as being free */
1913 /* modify all stack values */
1914 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1915 i
= p
[0] & VT_VALMASK
;
1923 /* find a free register. If none, save one register */
1928 /* find a free register */
1929 for(r
=0;r
<NB_REGS
;r
++) {
1930 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1931 i
= p
[0] & VT_VALMASK
;
1939 /* no register left : free the first one on the stack (very
1940 important to start from the bottom to ensure that we don't
1941 spill registers used in gen_op()) */
1942 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1943 r
= p
[0] & VT_VALMASK
;
1955 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1956 r
= p
[0] & VT_VALMASK
;
1963 /* move register 's' to 'r', and flush previous value of r to memory
1973 /* convert a stack entry in register. lvalues are converted as
1974 values. Cannot be used if cannot be converted to register value
1975 (such as structures). */
1979 r
= p
[0] & VT_VALMASK
;
1980 if (r
>= VT_CONST
|| (p
[0] & VT_LVAL
))
1982 /* NOTE: get_reg can modify p[] */
1983 load(r
, p
[0], p
[1]);
1984 p
[0] = (p
[0] & VT_TYPE
) | r
;
1990 if (vstack_ptr
>= vstack
+ VSTACK_SIZE
)
1991 error("memory full");
1994 /* cannot let cpu flags if other instruction are generated */
1995 /* XXX: VT_JMP test too ? */
1996 if ((vt
& VT_VALMASK
) == VT_CMP
)
1997 gvp(vstack_ptr
- 2);
2000 void vpop(int *ft
, int *fc
)
2002 *fc
= *--vstack_ptr
;
2003 *ft
= *--vstack_ptr
;
2006 /* generate a value in a register from vt and vc */
2011 r
= gvp(vstack_ptr
- 2);
2016 /* handle constant optimizations and various machine independant opt */
2019 int fr
, ft
, fc
, r
, c1
, c2
, n
;
2023 c1
= (vt
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
;
2024 c2
= (ft
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
;
2027 case '+': vc
+= fc
; break;
2028 case '-': vc
-= fc
; break;
2029 case '&': vc
&= fc
; break;
2030 case '^': vc
^= fc
; break;
2031 case '|': vc
|= fc
; break;
2032 case '*': vc
*= fc
; break;
2034 case '/': vc
/= fc
; break; /* XXX: zero case ? */
2035 case '%': vc
%= fc
; break; /* XXX: zero case ? */
2036 case TOK_UDIV
: vc
= (unsigned)vc
/ fc
; break; /* XXX: zero case ? */
2037 case TOK_UMOD
: vc
= (unsigned)vc
% fc
; break; /* XXX: zero case ? */
2038 case TOK_SHL
: vc
<<= fc
; break;
2039 case TOK_SHR
: vc
= (unsigned)vc
>> fc
; break;
2040 case TOK_SAR
: vc
>>= fc
; break;
2042 case TOK_ULT
: vc
= (unsigned)vc
< (unsigned)fc
; break;
2043 case TOK_UGE
: vc
= (unsigned)vc
>= (unsigned)fc
; break;
2044 case TOK_EQ
: vc
= vc
== fc
; break;
2045 case TOK_NE
: vc
= vc
!= fc
; break;
2046 case TOK_ULE
: vc
= (unsigned)vc
<= (unsigned)fc
; break;
2047 case TOK_UGT
: vc
= (unsigned)vc
> (unsigned)fc
; break;
2048 case TOK_LT
: vc
= vc
< fc
; break;
2049 case TOK_GE
: vc
= vc
>= fc
; break;
2050 case TOK_LE
: vc
= vc
<= fc
; break;
2051 case TOK_GT
: vc
= vc
> fc
; break;
2053 case TOK_LAND
: vc
= vc
&& fc
; break;
2054 case TOK_LOR
: vc
= vc
|| fc
; break;
2059 /* if commutative ops, put c2 as constant */
2060 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
2061 op
== '|' || op
== '*')) {
2066 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
2069 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
2070 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
2074 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
2075 /* try to use shifts instead of muls or divs */
2076 if (fc
> 0 && (fc
& (fc
- 1)) == 0) {
2085 else if (op
== TOK_PDIV
)
2097 r
= gvp(vstack_ptr
- 4);
2098 fr
= gvp(vstack_ptr
- 2);
2101 /* call low level op generator */
2107 int pointed_size(int t
)
2109 return type_size(pointed_type(t
), &t
);
2112 /* generic gen_op: handles types problems */
2118 t1
= vstack_ptr
[-4];
2119 t2
= vstack_ptr
[-2];
2120 if (op
== '+' | op
== '-') {
2121 if ((t1
& VT_BTYPE
) == VT_PTR
&&
2122 (t2
& VT_BTYPE
) == VT_PTR
) {
2124 error("invalid type");
2125 /* XXX: check that types are compatible */
2126 u
= pointed_size(t1
);
2129 vstack_ptr
[-2] &= ~VT_TYPE
; /* set to integer */
2132 } else if ((t1
& VT_BTYPE
) == VT_PTR
||
2133 (t2
& VT_BTYPE
) == VT_PTR
) {
2134 if ((t2
& VT_BTYPE
) == VT_PTR
) {
2135 swap(vstack_ptr
- 4, vstack_ptr
- 2);
2136 swap(vstack_ptr
- 3, vstack_ptr
- 1);
2139 /* stack-4 contains pointer, stack-2 value to add */
2140 vset(VT_CONST
, pointed_size(vstack_ptr
[-4]));
2144 /* put again type if gen_opc() swaped operands */
2145 vt
= (vt
& ~VT_TYPE
) | (t1
& VT_TYPE
);
2150 /* XXX: test types and compute returned value */
2151 if ((t1
| t2
) & VT_UNSIGNED
||
2152 (t1
& VT_BTYPE
) == VT_PTR
||
2153 (t2
& VT_BTYPE
) == VT_PTR
) {
2160 else if (op
== TOK_LT
)
2162 else if (op
== TOK_GT
)
2164 else if (op
== TOK_LE
)
2166 else if (op
== TOK_GE
)
2173 /* cast (vt, vc) to 't' type */
2174 void gen_cast(int t
)
2177 r
= vt
& VT_VALMASK
;
2178 if (!(t
& VT_LVAL
)) {
2179 /* if not lvalue, then we convert now */
2180 if ((t
& VT_TYPE
& ~VT_UNSIGNED
) == VT_BYTE
)
2182 else if ((t
& VT_TYPE
& ~VT_UNSIGNED
) == VT_SHORT
)
2187 if (t
& VT_UNSIGNED
) {
2188 vset(VT_CONST
, (1 << bits
) - 1);
2192 vset(VT_CONST
, bits
);
2195 vset(VT_CONST
, bits
);
2200 vt
= (vt
& ~VT_TYPE
) | t
;
2203 /* return type size. Put alignment at 'a' */
2204 int type_size(int t
, int *a
)
2210 if (bt
== VT_STRUCT
) {
2212 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
2213 *a
= 4; /* XXX: cannot store it yet. Doing that is safe */
2215 } else if (t
& VT_ARRAY
) {
2216 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
2217 return type_size(s
->t
, a
) * s
->c
;
2218 } else if (bt
== VT_PTR
||
2223 } else if (bt
== VT_SHORT
) {
2227 /* void or function */
2233 /* return the pointed type of t */
2234 int pointed_type(int t
)
2237 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
2238 return s
->t
| (t
& ~VT_TYPE
);
2241 int mk_pointer(int t
)
2246 return VT_PTR
| (p
<< VT_STRUCT_SHIFT
) | (t
& ~VT_TYPE
);
2249 /* store value in lvalue pushed on stack */
2252 int ft
, fc
, r
, t
, size
, align
;
2255 if ((vt
& VT_BTYPE
) == VT_STRUCT
) {
2256 /* if structure, only generate pointer */
2257 /* structure assignment : generate memcpy */
2258 /* XXX: optimize if small size */
2264 size
= type_size(vt
, &align
);
2265 vset(VT_CONST
, size
);
2277 vset(VT_CONST
, (int)&memcpy
);
2280 /* generate again current type */
2284 r
= gv(); /* generate value */
2286 ft
= vstack_ptr
[-4];
2287 fc
= vstack_ptr
[-3];
2288 /* if lvalue was saved on stack, must read it */
2289 if ((ft
& VT_VALMASK
) == VT_LLOCAL
) {
2291 load(t
, VT_LOCAL
| VT_LVAL
, fc
);
2292 ft
= (ft
& ~VT_VALMASK
) | t
;
2299 /* post defines POST/PRE add. c is the token ++ or -- */
2305 vpush(); /* room for returned value */
2306 vpush(); /* save lvalue */
2308 vpush(); /* save value */
2310 /* duplicate value */
2312 load(r1
, r
, 0); /* move r to r1 */
2313 vstack_ptr
[-6] = (vt
& VT_TYPE
) | r1
;
2317 vset(VT_CONST
, c
- TOK_MID
);
2319 vstore(); /* store value */
2324 /* enum/struct/union declaration */
2325 int struct_decl(int u
)
2327 int a
, t
, b
, v
, size
, align
, maxalign
, c
;
2330 a
= tok
; /* save decl type */
2335 /* struct already defined ? return it */
2336 /* XXX: check consistency */
2337 if (s
= sym_find(v
| SYM_STRUCT
)) {
2339 error("invalid type");
2345 s
= sym_push(v
| SYM_STRUCT
, a
, 0);
2346 /* put struct/union/enum name in type */
2348 u
= u
| (v
<< VT_STRUCT_SHIFT
);
2353 error("struct/union/enum already defined");
2354 /* cannot be empty */
2359 if (a
== TOK_ENUM
) {
2366 /* enum symbols have static storage */
2367 sym_push(v
, VT_CONST
| VT_STATIC
, c
);
2374 t
= type_decl(&v
, b
, TYPE_DIRECT
);
2375 if ((t
& VT_BTYPE
) == VT_FUNC
||
2376 (t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
)))
2377 error("invalid type");
2378 /* XXX: align & correct type size */
2380 size
= type_size(t
, &align
);
2381 if (a
== TOK_STRUCT
) {
2382 c
= (c
+ align
- 1) & -align
;
2383 ss
= sym_push(v
, t
, c
);
2386 ss
= sym_push(v
, t
, 0);
2390 if (align
> maxalign
)
2394 if (tok
== ';' || tok
== -1)
2404 /* size for struct/union, dummy for enum */
2405 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
2410 /* return 0 if no type declaration. otherwise, return the basic type
2412 XXX: A '2' is ored to ensure non zero return if int type.
2421 if (tok
== TOK_ENUM
) {
2422 t
|= struct_decl(VT_ENUM
);
2423 } else if (tok
== TOK_STRUCT
|| tok
== TOK_UNION
) {
2424 t
|= struct_decl(VT_STRUCT
);
2426 if (tok
== TOK_CHAR
) {
2428 } else if (tok
== TOK_VOID
) {
2430 } else if (tok
== TOK_SHORT
) {
2432 } else if (tok
== TOK_INT
|
2433 (tok
>= TOK_CONST
& tok
<= TOK_INLINE
)) {
2435 } else if (tok
== TOK_FLOAT
|| tok
== TOK_DOUBLE
) {
2436 /* We allow that to compile standard headers */
2437 // warning("floats not supported");
2438 } else if (tok
== TOK_EXTERN
) {
2440 } else if (tok
== TOK_STATIC
) {
2442 } else if (tok
== TOK_UNSIGNED
) {
2444 } else if (tok
== TOK_TYPEDEF
) {
2448 if (!s
|| !(s
->t
& VT_TYPEDEF
))
2450 t
|= (s
->t
& ~VT_TYPEDEF
);
2459 int post_type(int t
)
2461 int p
, n
, pt
, l
, t1
;
2462 Sym
**plast
, *s
, *first
;
2465 /* function declaration */
2470 while (tok
!= ')') {
2471 /* read param name and compute offset */
2472 if (l
!= FUNC_OLD
) {
2473 if (!(pt
= ist())) {
2475 error("invalid type");
2481 if ((pt
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
2484 pt
= type_decl(&n
, pt
, TYPE_DIRECT
| TYPE_ABSTRACT
);
2491 /* array must be transformed to pointer according to ANSI C */
2493 s
= sym_push(n
| SYM_FIELD
, pt
, 0);
2498 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
2506 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
2507 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
));
2508 /* we push a anonymous symbol which will contain the function prototype */
2510 s
= sym_push(p
, t
, l
);
2512 t
= t1
| VT_FUNC
| (p
<< VT_STRUCT_SHIFT
);
2513 } else if (tok
== '[') {
2514 /* array definition */
2520 error("invalid array size");
2523 /* parse next post type */
2524 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
2525 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
));
2527 /* we push a anonymous symbol which will contain the array
2531 t
= t1
| VT_ARRAY
| VT_PTR
| (p
<< VT_STRUCT_SHIFT
);
2536 /* Read a type declaration (except basic type), and return the
2537 type. If v is true, then also put variable name in 'vc' */
2538 int type_decl(int *v
, int t
, int td
)
2543 t
= t
& -3; /* suppress the ored '2' */
2544 while (tok
== '*') {
2546 while (tok
== TOK_CONST
|| tok
== TOK_VOLATILE
|| tok
== TOK_RESTRICT
)
2551 /* recursive type */
2552 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
2555 u
= type_decl(v
, 0, td
);
2559 /* type identifier */
2560 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
2564 if (!(td
& TYPE_ABSTRACT
))
2565 expect("identifier");
2569 /* append t at the end of u */
2575 s
= sym_find((unsigned)p
>> VT_STRUCT_SHIFT
);
2585 /* define a new external reference to a function 'v' of type 'u' */
2586 Sym
*external_sym(int v
, int u
)
2591 /* push forward reference */
2592 s
= sym_push1(&global_stack
,
2593 v
, u
| VT_CONST
| VT_FORWARD
, 0);
2602 if ((vt
& VT_BTYPE
) != VT_PTR
)
2604 vt
= pointed_type(vt
);
2605 if (!(vt
& VT_ARRAY
)) /* an array is never an lvalue */
2611 int n
, t
, ft
, fc
, p
, align
, size
;
2615 if (tok
== TOK_NUM
|| tok
== TOK_CCHAR
|| tok
== TOK_LCHAR
) {
2616 vset(VT_CONST
, tokc
);
2618 } else if (tok
== TOK___FUNC__
) {
2619 /* special function name identifier */
2620 /* generate (char *) type */
2621 vset(VT_CONST
| mk_pointer(VT_BYTE
), glo
);
2622 strcpy((void *)glo
, funcname
);
2623 glo
+= strlen(funcname
) + 1;
2625 } else if (tok
== TOK_LSTR
) {
2628 } else if (tok
== TOK_STR
) {
2629 /* string parsing */
2632 type_size(t
, &align
);
2633 glo
= (glo
+ align
- 1) & -align
;
2635 /* we must declare it as an array first to use initializer parser */
2636 t
= VT_CONST
| VT_ARRAY
| mk_pointer(t
);
2637 decl_initializer(t
, glo
, 1, 0);
2638 glo
+= type_size(t
, &align
);
2639 /* put it as pointer */
2640 vset(t
& ~VT_ARRAY
, fc
);
2647 ft
= type_decl(&n
, t
, TYPE_ABSTRACT
);
2649 /* check ISOC99 compound literal */
2651 /* data is allocated locally by default */
2656 /* all except arrays are lvalues */
2657 if (!(ft
& VT_ARRAY
))
2659 fc
= decl_initializer_alloc(ft
, 1);
2669 } else if (t
== '*') {
2672 } else if (t
== '&') {
2674 /* functions names must be treated as function pointers,
2675 except for unary '&' and sizeof. Since we consider that
2676 functions are not lvalues, we only have to handle it
2677 there and in function calls. */
2678 if ((vt
& VT_BTYPE
) != VT_FUNC
)
2680 vt
= mk_pointer(vt
& VT_LVALN
);
2684 if ((vt
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
)
2686 else if ((vt
& VT_VALMASK
) == VT_CMP
)
2689 vset(VT_JMP
, gtst(1, 0));
2700 if (t
== TOK_SIZEOF
) {
2701 /* XXX: some code can be generated */
2705 vt
= type_decl(&n
, t
, TYPE_ABSTRACT
);
2712 vset(VT_CONST
, type_size(vt
, &t
));
2714 if (t
== TOK_INC
| t
== TOK_DEC
) {
2717 } else if (t
== '-') {
2727 error("'%s' undeclared", get_tok_str(t
, 0));
2728 /* for simple function calls, we tolerate undeclared
2729 external reference */
2731 sym_push1(&global_stack
, p
, 0, FUNC_OLD
);
2732 /* int() function */
2733 s
= external_sym(t
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
));
2736 /* if forward reference, we must point to s */
2737 if (vt
& VT_FORWARD
)
2742 /* post operations */
2744 if (tok
== TOK_INC
| tok
== TOK_DEC
) {
2747 } else if (tok
== '.' | tok
== TOK_ARROW
) {
2749 if (tok
== TOK_ARROW
)
2754 /* expect pointer on structure */
2755 if ((vt
& VT_BTYPE
) != VT_STRUCT
)
2756 expect("struct or union");
2757 s
= sym_find(((unsigned)vt
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
2760 while (s
= s
->next
) {
2765 error("field not found");
2766 /* add field offset to pointer */
2767 vt
= (vt
& ~VT_TYPE
) | VT_INT
; /* change type to int */
2769 vset(VT_CONST
, s
->c
);
2771 /* change type to field type, and set to lvalue */
2772 vt
= (vt
& ~VT_TYPE
) | s
->t
;
2773 /* an array is never an lvalue */
2774 if (!(vt
& VT_ARRAY
))
2777 } else if (tok
== '[') {
2784 } else if (tok
== '(') {
2788 if ((vt
& VT_BTYPE
) != VT_FUNC
) {
2789 /* pointer test (no array accepted) */
2790 if ((vt
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
2791 vt
= pointed_type(vt
);
2792 if ((vt
& VT_BTYPE
) != VT_FUNC
)
2796 expect("function pointer");
2799 vt
&= ~VT_LVAL
; /* no lvalue */
2802 /* get return type */
2803 s
= sym_find((unsigned)vt
>> VT_STRUCT_SHIFT
);
2804 vpush(); /* push function address */
2805 save_regs(); /* save used temporary registers */
2808 #ifdef INVERT_FUNC_PARAMS
2810 int *str
, len
, parlevel
, *saved_macro_ptr
;
2813 /* read each argument and store it on a stack */
2814 /* XXX: merge it with macro args ? */
2816 while (tok
!= ')') {
2820 while ((parlevel
> 0 || (tok
!= ')' && tok
!= ',')) &&
2824 else if (tok
== ')')
2826 tok_add2(&str
, &len
, tok
, tokc
);
2829 tok_add(&str
, &len
, -1); /* end of file added */
2830 tok_add(&str
, &len
, 0);
2831 sym_push2(&args
, 0, 0, (int)str
);
2839 /* now generate code in reverse order by reading the stack */
2840 saved_macro_ptr
= macro_ptr
;
2842 macro_ptr
= (int *)args
->c
;
2846 expect("',' or ')'");
2849 free((int *)args
->c
);
2853 macro_ptr
= saved_macro_ptr
;
2858 /* compute first implicit argument if a structure is returned */
2859 if ((s
->t
& VT_BTYPE
) == VT_STRUCT
) {
2860 /* get some space for the returned structure */
2861 size
= type_size(s
->t
, &align
);
2862 loc
= (loc
- size
) & -align
;
2863 rett
= s
->t
| VT_LOCAL
| VT_LVAL
;
2864 /* pass it as 'int' to avoid structure arg passing
2866 vset(VT_INT
| VT_LOCAL
, loc
);
2870 rett
= s
->t
| FUNC_RET_REG
; /* return in register */
2873 #ifndef INVERT_FUNC_PARAMS
2874 while (tok
!= ')') {
2893 int is_compatible_types(int t1
, int t2
)
2900 bt1
= t1
& VT_BTYPE
;
2901 bt2
= t2
& VT_BTYPE
;
2902 if (bt1
== VT_PTR
) {
2903 t1
= pointed_type(t1
);
2904 /* if function, then convert implictely to function pointer */
2905 if (bt2
!= VT_FUNC
) {
2908 t2
= pointed_type(t2
);
2910 /* void matches everything */
2913 if (t1
== VT_VOID
|| t2
== VT_VOID
)
2915 return is_compatible_types(t1
, t2
);
2916 } else if (bt1
== VT_STRUCT
) {
2918 } else if (bt1
== VT_FUNC
) {
2921 s1
= sym_find(((unsigned)t1
>> VT_STRUCT_SHIFT
));
2922 s2
= sym_find(((unsigned)t2
>> VT_STRUCT_SHIFT
));
2923 if (!is_compatible_types(s1
->t
, s2
->t
))
2925 /* XXX: not complete */
2926 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
2930 while (s1
!= NULL
) {
2933 if (!is_compatible_types(s1
->t
, s2
->t
))
2942 /* XXX: not complete */
2947 int check_assign_types(int t1
, int t2
)
2951 if ((t1
& VT_BTYPE
) == VT_PTR
&&
2952 (t2
& VT_BTYPE
) == VT_FUNC
) {
2953 return is_compatible_types(pointed_type(t1
), t2
);
2955 return is_compatible_types(t1
, t2
);
2966 (tok
>= TOK_A_MOD
& tok
<= TOK_A_DIV
) |
2967 tok
== TOK_A_XOR
| tok
== TOK_A_OR
|
2968 tok
== TOK_A_SHL
| tok
== TOK_A_SAR
) {
2975 if (!check_assign_types(vstack_ptr
[-2], vt
))
2976 warning("incompatible types");
2994 while ((l
== 0 & (tok
== '*' | tok
== '/' | tok
== '%')) |
2995 (l
== 1 & (tok
== '+' | tok
== '-')) |
2996 (l
== 2 & (tok
== TOK_SHL
| tok
== TOK_SAR
)) |
2997 (l
== 3 & ((tok
>= TOK_ULE
& tok
<= TOK_GT
) |
2998 tok
== TOK_ULT
| tok
== TOK_UGE
)) |
2999 (l
== 4 & (tok
== TOK_EQ
| tok
== TOK_NE
)) |
3000 (l
== 5 & tok
== '&') |
3001 (l
== 6 & tok
== '^') |
3002 (l
== 7 & tok
== '|') |
3003 (l
== 8 & tok
== TOK_LAND
) |
3004 (l
== 9 & tok
== TOK_LOR
)) {
3014 /* only used if non constant */
3022 if (tok
!= TOK_LAND
) {
3042 if (tok
!= TOK_LOR
) {
3055 /* XXX: better constant handling */
3058 int t
, u
, c
, r1
, r2
;
3085 vt
= (vt
& VT_TYPE
) | r1
;
3107 if ((vt
& (VT_CONST
| VT_LVAL
)) != VT_CONST
)
3113 /* return the label token if current token is a label, otherwise
3119 /* fast test first */
3120 if (tok
< TOK_UIDENT
)
3129 /* XXX: may not work in all cases (macros ?) */
3138 void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
, int case_reg
)
3143 if (tok
== TOK_IF
) {
3150 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3152 if (c
== TOK_ELSE
) {
3156 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3157 gsym(d
); /* patch else jmp */
3160 } else if (tok
== TOK_WHILE
) {
3168 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
3169 oad(0xe9, d
- ind
- 5); /* jmp */
3172 } else if (tok
== '{') {
3175 s
= local_stack
.top
;
3176 while (tok
!= '}') {
3179 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3181 /* pop locally defined symbols */
3182 sym_pop(&local_stack
, s
);
3184 } else if (tok
== TOK_RETURN
) {
3187 if ((func_vt
& VT_BTYPE
) == VT_STRUCT
) {
3188 /* if returning structure, must copy it to implicit
3189 first pointer arg location */
3190 vset(mk_pointer(func_vt
) | VT_LOCAL
| VT_LVAL
, func_vc
);
3195 if ((func_vt
& VT_BTYPE
) == VT_STRUCT
) {
3196 /* copy structure value to pointer */
3199 /* move return value to standard return register */
3200 move_reg(FUNC_RET_REG
, gv());
3204 rsym
= gjmp(rsym
); /* jmp */
3205 } else if (tok
== TOK_BREAK
) {
3208 error("cannot break");
3209 *bsym
= gjmp(*bsym
);
3212 } else if (tok
== TOK_CONTINUE
) {
3215 error("cannot continue");
3216 *csym
= gjmp(*csym
);
3219 } else if (tok
== TOK_FOR
) {
3239 oad(0xe9, d
- ind
- 5); /* jmp */
3243 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
3244 oad(0xe9, c
- ind
- 5); /* jmp */
3248 if (tok
== TOK_DO
) {
3253 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
3264 if (tok
== TOK_SWITCH
) {
3273 block(&a
, csym
, &b
, &c
, case_reg
);
3274 /* if no default, jmp after switch */
3282 if (tok
== TOK_CASE
) {
3292 *case_sym
= gtst(1, 0);
3294 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3296 if (tok
== TOK_DEFAULT
) {
3302 error("too many 'default'");
3304 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3306 if (tok
== TOK_GOTO
) {
3308 s
= sym_find1(&label_stack
, tok
);
3309 /* put forward definition if needed */
3311 s
= sym_push1(&label_stack
, tok
, VT_FORWARD
, 0);
3312 /* label already defined */
3313 if (s
->t
& VT_FORWARD
)
3314 s
->c
= gjmp(s
->c
); /* jmp xxx */
3316 oad(0xe9, s
->c
- ind
- 5); /* jmp xxx */
3323 s
= sym_find1(&label_stack
, b
);
3325 if (!(s
->t
& VT_FORWARD
))
3326 error("multiple defined label");
3331 sym_push1(&label_stack
, b
, 0, ind
);
3333 /* we accept this, but it is a mistake */
3335 warning("deprecated use of label at end of compound statement");
3337 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3339 /* expression case */
3348 /* t is the array or struct type. c is the array or struct
3349 address. cur_index/cur_field is the pointer to the current
3350 value. 'size_only' is true if only size info is needed (only used
3352 void decl_designator(int t
, int c
,
3353 int *cur_index
, Sym
**cur_field
,
3357 int notfirst
, index
, align
, l
;
3360 if (gnu_ext
&& (l
= is_label()) != 0)
3363 while (tok
== '[' || tok
== '.') {
3365 if (!(t
& VT_ARRAY
))
3366 expect("array type");
3367 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3369 index
= expr_const();
3370 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
3371 expect("invalid index");
3375 t
= pointed_type(t
);
3376 c
+= index
* type_size(t
, &align
);
3382 if ((t
& VT_BTYPE
) != VT_STRUCT
)
3383 expect("struct/union type");
3384 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
3396 t
= f
->t
| (t
& ~VT_TYPE
);
3411 t
= pointed_type(t
);
3412 c
+= index
* type_size(t
, &align
);
3416 error("too many field init");
3417 t
= f
->t
| (t
& ~VT_TYPE
);
3421 decl_initializer(t
, c
, 0, size_only
);
3424 /* store a value or an expression directly in global data or in local array */
3426 void init_putv(int t
, int c
, int v
, int is_expr
)
3428 int saved_global_expr
;
3430 if ((t
& VT_VALMASK
) == VT_CONST
) {
3432 /* compound literals must be allocated globally in this case */
3433 saved_global_expr
= global_expr
;
3436 global_expr
= saved_global_expr
;
3438 if ((t
& VT_BTYPE
) == VT_BYTE
)
3440 else if ((t
& VT_BTYPE
) == VT_SHORT
)
3456 /* put zeros for variable based init */
3457 void init_putz(int t
, int c
, int size
)
3461 if ((t
& VT_VALMASK
) == VT_CONST
) {
3462 /* nothing to do because global are already set to zero */
3465 vset(VT_CONST
, size
);
3471 vset(VT_CONST
, (int)&memset
);
3476 /* 't' contains the type and storage info. c is the address of the
3477 object. 'first' is true if array '{' must be read (multi dimension
3478 implicit array init handling). 'size_only' is true if size only
3479 evaluation is wanted (only for arrays). */
3480 void decl_initializer(int t
, int c
, int first
, int size_only
)
3482 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
3483 int t1
, size1
, align1
;
3488 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3491 t1
= pointed_type(t
);
3492 size1
= type_size(t1
, &align1
);
3495 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
3501 /* only parse strings here if correct type (otherwise: handle
3502 them as ((w)char *) expressions */
3503 if ((tok
== TOK_LSTR
&&
3504 (t1
& VT_BTYPE
) == VT_INT
) ||
3506 (t1
& VT_BTYPE
) == VT_BYTE
)) {
3507 /* XXX: move multiple string parsing in parser ? */
3508 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
3509 ts
= (TokenSym
*)tokc
;
3510 /* compute maximum number of chars wanted */
3512 if (n
>= 0 && nb
> (n
- array_length
))
3513 nb
= n
- array_length
;
3516 warning("initializer-string for array is too long");
3518 init_putv(t1
, c
+ (array_length
+ i
) * size1
,
3525 /* only add trailing zero if enough storage (no
3526 warning in this case since it is standard) */
3527 if (n
< 0 || array_length
< n
) {
3529 init_putv(t1
, c
+ (array_length
* size1
), 0, 0);
3535 while (tok
!= '}') {
3536 decl_designator(t
, c
, &index
, NULL
, size_only
);
3537 if (n
>= 0 && index
>= n
)
3538 error("index too large");
3539 /* must put zero in holes (note that doing it that way
3540 ensures that it even works with designators) */
3541 if (!size_only
&& array_length
< index
) {
3542 init_putz(t1
, c
+ array_length
* size1
,
3543 (index
- array_length
) * size1
);
3546 if (index
> array_length
)
3547 array_length
= index
;
3548 /* special test for multi dimensional arrays (may not
3549 be strictly correct if designators are used at the
3551 if (index
>= n
&& no_oblock
)
3560 /* put zeros at the end */
3561 if (!size_only
&& n
>= 0 && array_length
< n
) {
3562 init_putz(t1
, c
+ array_length
* size1
,
3563 (n
- array_length
) * size1
);
3565 /* patch type size if needed */
3567 s
->c
= array_length
;
3568 } else if ((t
& VT_BTYPE
) == VT_STRUCT
&& tok
== '{') {
3569 /* XXX: union needs only one init */
3571 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
3576 while (tok
!= '}') {
3577 decl_designator(t
, c
, NULL
, &f
, size_only
);
3578 /* fill with zero between fields */
3580 if (!size_only
&& array_length
< index
) {
3581 init_putz(t
, c
+ array_length
,
3582 index
- array_length
);
3584 index
= index
+ type_size(f
->t
, &align1
);
3585 if (index
> array_length
)
3586 array_length
= index
;
3592 /* put zeros at the end */
3593 if (!size_only
&& array_length
< n
) {
3594 init_putz(t
, c
+ array_length
,
3598 } else if (tok
== '{') {
3600 decl_initializer(t
, c
, first
, size_only
);
3602 } else if (size_only
) {
3603 /* just skip expression */
3605 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
3609 else if (tok
== ')')
3614 init_putv(t
, c
, 0, 1);
3618 /* parse an initializer for type 't' if 'has_init' is true, and
3619 allocate space in local or global data space. The allocated address
3621 int decl_initializer_alloc(int t
, int has_init
)
3623 int size
, align
, addr
, tok1
;
3624 int *init_str
, init_len
, level
, *saved_macro_ptr
;
3626 size
= type_size(t
, &align
);
3627 /* If unknown size, we must evaluate it before
3628 evaluating initializers because
3629 initializers can generate global data too
3630 (e.g. string pointers or ISOC99 compound
3631 literals). It also simplifies local
3632 initializers handling */
3635 saved_macro_ptr
= NULL
; /* avoid warning */
3639 error("unknown type size");
3640 /* get all init string */
3642 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
3644 error("unexpect end of file in initializer");
3645 tok_add2(&init_str
, &init_len
, tok
, tokc
);
3648 else if (tok
== '}') {
3656 tok_add(&init_str
, &init_len
, -1);
3657 tok_add(&init_str
, &init_len
, 0);
3660 saved_macro_ptr
= macro_ptr
;
3661 macro_ptr
= init_str
;
3663 decl_initializer(t
, 0, 1, 1);
3664 /* prepare second initializer parsing */
3665 macro_ptr
= init_str
;
3668 /* if still unknown size, error */
3669 size
= type_size(t
, &align
);
3671 error("unknown type size");
3673 if ((t
& VT_VALMASK
) == VT_LOCAL
) {
3674 loc
= (loc
- size
) & -align
;
3677 glo
= (glo
+ align
- 1) & -align
;
3679 /* very important to increment global
3680 pointer at this time because
3681 initializers themselves can create new
3686 decl_initializer(t
, addr
, 1, 0);
3687 /* restore parse state if needed */
3690 macro_ptr
= saved_macro_ptr
;
3698 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
3701 int *a
, t
, b
, v
, u
, addr
, has_init
, size
, align
;
3707 /* skip redundant ';' */
3708 /* XXX: find more elegant solution */
3713 /* special test for old K&R protos without explicit int
3714 type. Only accepted when defining global data */
3715 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
3719 if (((b
& VT_BTYPE
) == VT_ENUM
||
3720 (b
& VT_BTYPE
) == VT_STRUCT
) &&
3722 /* we accept no variable after */
3726 while (1) { /* iterate thru each declaration */
3727 t
= type_decl(&v
, b
, TYPE_DIRECT
);
3730 error("cannot use local functions");
3732 expect("function definition");
3733 /* patch forward references */
3734 if ((sym
= sym_find(v
)) && (sym
->t
& VT_FORWARD
)) {
3735 greloc_patch(sym
, ind
);
3736 sym
->t
= VT_CONST
| t
;
3738 /* put function address */
3739 sym_push1(&global_stack
, v
, VT_CONST
| t
, ind
);
3741 funcname
= get_tok_str(v
, 0);
3742 /* push a dummy symbol to enable local sym storage */
3743 sym_push1(&local_stack
, 0, 0, 0);
3744 /* define parameters */
3745 sym
= sym_find((unsigned)t
>> VT_STRUCT_SHIFT
);
3746 /* XXX: the following is x86 dependant -> move it to
3749 /* if the function returns a structure, then add an
3750 implicit pointer parameter */
3752 if ((func_vt
& VT_BTYPE
) == VT_STRUCT
) {
3756 while (sym
= sym
->next
) {
3758 sym_push(sym
->v
& ~SYM_FIELD
,
3759 u
| VT_LOCAL
| VT_LVAL
,
3761 if ((u
& VT_BTYPE
) == VT_STRUCT
) {
3762 #ifdef FUNC_STRUCT_PARAM_AS_PTR
3763 /* structs are passed as pointer */
3766 /* structs are directly put on stack (x86
3768 size
= type_size(u
, &align
);
3769 size
= (size
+ 3) & ~3;
3772 /* XXX: size will be different someday */
3778 o(0xe58955); /* push %ebp, mov %esp, %ebp */
3779 a
= (int *)oad(0xec81, 0); /* sub $xxx, %esp */
3781 block(0, 0, 0, 0, 0);
3783 o(0xc3c9); /* leave, ret */
3784 *a
= (-loc
+ 3) & -4; /* align local size to word &
3785 save local variables */
3786 sym_pop(&label_stack
, 0); /* reset label stack */
3787 sym_pop(&local_stack
, 0); /* reset local stack */
3788 funcname
= ""; /* for safety */
3789 func_vt
= VT_VOID
; /* for safety */
3792 if (b
& VT_TYPEDEF
) {
3793 /* save typedefed type */
3794 /* XXX: test storage specifiers ? */
3795 sym_push(v
, t
| VT_TYPEDEF
, 0);
3796 } else if ((t
& VT_BTYPE
) == VT_FUNC
) {
3797 /* external function definition */
3800 /* not lvalue if array */
3801 if (!(t
& VT_ARRAY
))
3803 if (b
& VT_EXTERN
) {
3804 /* external variable */
3811 has_init
= (tok
== '=');
3814 addr
= decl_initializer_alloc(u
, has_init
);
3815 if (l
== VT_CONST
) {
3816 /* global scope: see if already defined */
3820 if (!is_compatible_types(sym
->t
, u
))
3821 error("incompatible types for redefinition of '%s'",
3823 if (!(sym
->t
& VT_FORWARD
))
3824 error("redefinition of '%s'", get_tok_str(v
, 0));
3825 greloc_patch(sym
, addr
);
3828 sym_push(v
, u
, addr
);
3842 /* put all global symbols in the extern stack and do all the
3843 resolving which can be done without using external symbols from DLLs */
3844 /* XXX: could try to verify types, but would not to save them in
3846 void resolve_global_syms(void)
3848 Sym
*s
, *s1
, *ext_sym
;
3851 s
= global_stack
.top
;
3854 /* do not save static or typedefed symbols or types */
3855 if (!(s
->t
& (VT_STATIC
| VT_TYPEDEF
)) &&
3856 !(s
->v
& (SYM_FIELD
| SYM_STRUCT
)) &&
3857 (s
->v
< SYM_FIRST_ANOM
)) {
3858 ext_sym
= sym_find1(&extern_stack
, s
->v
);
3860 /* if the symbol do not exist, we simply save it */
3861 sym_push1(&extern_stack
, s
->v
, s
->t
, s
->c
);
3862 } else if (ext_sym
->t
& VT_FORWARD
) {
3863 /* external symbol already exists, but only as forward
3865 if (!(s
->t
& VT_FORWARD
)) {
3866 /* s is not forward, so we can relocate all symbols */
3867 greloc_patch(ext_sym
, s
->c
);
3869 /* the two symbols are forward: merge them */
3870 p
= (Reloc
**)&ext_sym
->c
;
3876 /* external symbol already exists and is defined :
3877 patch all references to it */
3878 if (!(s
->t
& VT_FORWARD
))
3879 error("'%s' defined twice", get_tok_str(s
->v
, 0));
3880 greloc_patch(s
, ext_sym
->c
);
3887 /* compile a C file. Return non zero if errors. */
3888 int tcc_compile_file(const char *filename1
)
3892 filename
= (char *)filename1
;
3896 file
= fopen(filename
, "r");
3898 error("file '%s' not found", filename
);
3899 include_stack_ptr
= include_stack
;
3900 ifdef_stack_ptr
= ifdef_stack
;
3902 vstack_ptr
= vstack
;
3903 anon_sym
= SYM_FIRST_ANOM
;
3905 define_start
= define_stack
.top
;
3907 ch
= '\n'; /* needed to parse correctly first preprocessor command */
3911 expect("declaration");
3914 /* reset define stack, but leave -Dsymbols (may be incorrect if
3915 they are undefined) */
3916 sym_pop(&define_stack
, define_start
);
3918 resolve_global_syms();
3920 sym_pop(&global_stack
, NULL
);
3925 /* open a dynamic library so that its symbol are available for
3926 compiled programs */
3927 void open_dll(char *libname
)
3932 snprintf(buf
, sizeof(buf
), "lib%s.so", libname
);
3933 h
= dlopen(buf
, RTLD_GLOBAL
| RTLD_LAZY
);
3935 error((char *)dlerror());
3938 void resolve_extern_syms(void)
3944 s
= extern_stack
.top
;
3947 if (s
->t
& VT_FORWARD
) {
3948 /* if there is at least one relocation to do, then find it
3951 str
= get_tok_str(s
->v
, 0);
3952 addr
= (int)dlsym(NULL
, str
);
3954 error("unresolved external reference '%s'", str
);
3955 greloc_patch(s
, addr
);
3962 /* output a binary file (for testing) */
3963 void build_exe(char *filename
)
3966 f
= fopen(filename
, "w");
3967 fwrite((void *)prog
, 1, ind
- prog
, f
);
3971 int main(int argc
, char **argv
)
3975 char *p
, *r
, *outfile
;
3978 include_paths
[0] = "/usr/include";
3979 include_paths
[1] = "/usr/lib/tcc";
3980 include_paths
[2] = "/usr/local/lib/tcc";
3981 nb_include_paths
= 3;
3983 /* add all tokens */
3984 tok_ident
= TOK_IDENT
;
3985 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";
3989 tok_alloc(p
, r
- p
- 1);
3993 /* standard defines */
3994 define_symbol("__STDC__");
3996 define_symbol("__i386__");
3998 /* tiny C specific defines */
3999 define_symbol("__TINYC__");
4001 glo
= (int)malloc(DATA_SIZE
);
4002 memset((void *)glo
, 0, DATA_SIZE
);
4003 prog
= (int)malloc(TEXT_SIZE
);
4009 if (optind
>= argc
) {
4011 printf("tcc version 0.9.1 - Tiny C Compiler - Copyright (C) 2001 Fabrice Bellard\n"
4012 "usage: tcc [-Idir] [-Dsym] [-llib] [-i infile]... infile [infile_args...]\n");
4020 if (nb_include_paths
>= INCLUDE_PATHS_MAX
)
4021 error("too many include paths");
4022 include_paths
[nb_include_paths
++] = r
+ 2;
4023 } else if (r
[1] == 'D') {
4024 define_symbol(r
+ 2);
4025 } else if (r
[1] == 'l') {
4027 } else if (r
[1] == 'i') {
4030 tcc_compile_file(argv
[optind
++]);
4031 } else if (r
[1] == 'o') {
4032 /* currently, only for testing, so not documented */
4035 outfile
= argv
[optind
++];
4037 fprintf(stderr
, "invalid option -- '%s'\n", r
);
4042 tcc_compile_file(argv
[optind
]);
4044 resolve_extern_syms();
4050 s
= sym_find1(&extern_stack
, TOK_MAIN
);
4051 if (!s
|| (s
->t
& VT_FORWARD
))
4052 error("main() not defined");
4053 t
= (int (*)())s
->c
;
4054 return (*t
)(argc
- optind
, argv
+ optind
);