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
);
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 /* find a symbol and return its associated structure. 'st' is the
565 Sym
*sym_find1(SymStack
*st
, int v
)
569 s
= st
->hash
[v
% SYM_HASH_SIZE
];
578 Sym
*sym_push1(SymStack
*st
, int v
, int t
, int c
)
581 s
= sym_push2(&st
->top
, v
, t
, c
);
582 /* add in hash table */
583 ps
= &st
->hash
[s
->v
% SYM_HASH_SIZE
];
589 /* find a symbol in the right symbol space */
593 s
= sym_find1(&local_stack
, v
);
595 s
= sym_find1(&global_stack
, v
);
599 /* push a given symbol on the symbol stack */
600 Sym
*sym_push(int v
, int t
, int c
)
603 return sym_push1(&local_stack
, v
, t
, c
);
605 return sym_push1(&global_stack
, v
, t
, c
);
608 /* pop symbols until top reaches 'b' */
609 void sym_pop(SymStack
*st
, Sym
*b
)
616 /* free hash table entry */
617 st
->hash
[s
->v
% SYM_HASH_SIZE
] = s
->hash_next
;
624 /* undefined a hashed symbol (used for #undef). Its name is set to
626 void sym_undef(SymStack
*st
, Sym
*s
)
629 ss
= &st
->hash
[s
->v
% SYM_HASH_SIZE
];
630 while (*ss
!= NULL
) {
633 ss
= &(*ss
)->hash_next
;
639 /* no need to put that inline */
642 if (include_stack_ptr
== include_stack
)
644 /* pop include stack */
648 file
= include_stack_ptr
->file
;
649 filename
= include_stack_ptr
->filename
;
650 line_num
= include_stack_ptr
->line_num
;
654 /* read next char from current input file */
655 static inline void inp(void)
658 /* faster than fgetc */
659 ch1
= getc_unlocked(file
);
661 if (handle_eof() < 0)
668 // printf("ch1=%c 0x%x\n", ch1, ch1);
671 /* input with '\\n' handling */
672 static inline void minp(void)
677 if (ch
== '\\' && ch1
== '\n') {
681 //printf("ch=%c 0x%x\n", ch, ch);
685 /* same as minp, but also skip comments */
693 /* single line C++ comments */
695 while (ch1
!= '\n' && ch1
!= -1)
698 ch
= ' '; /* return space */
699 } else if (ch1
== '*') {
705 if (c
== '*' && ch1
== '/') {
707 ch
= ' '; /* return space */
719 void skip_spaces(void)
721 while (ch
== ' ' || ch
== '\t')
725 /* skip block of text until #else, #elif or #endif. skip also pairs of
727 void preprocess_skip()
743 (tok
== TOK_ELSE
|| tok
== TOK_ELIF
|| tok
== TOK_ENDIF
))
745 if (tok
== TOK_IF
|| tok
== TOK_IFDEF
|| tok
== TOK_IFNDEF
)
747 else if (tok
== TOK_ENDIF
)
753 inline int is_long_tok(int t
)
755 return (t
== TOK_NUM
||
756 t
== TOK_CCHAR
|| t
== TOK_LCHAR
||
757 t
== TOK_STR
|| t
== TOK_LSTR
);
760 void tok_add(int **tok_str
, int *tok_len
, int t
)
765 if ((len
& 63) == 0) {
766 str
= realloc(str
, (len
+ 64) * sizeof(int));
775 void tok_add2(int **tok_str
, int *tok_len
, int t
, int c
)
777 tok_add(tok_str
, tok_len
, t
);
779 tok_add(tok_str
, tok_len
, c
);
782 /* eval an expression for #if/#elif */
783 int expr_preprocess()
793 next(); /* do macro subst */
794 if (tok
== TOK_DEFINED
) {
799 c
= sym_find1(&define_stack
, tok
) != 0;
804 } else if (tok
>= TOK_IDENT
) {
805 /* if undefined macro */
809 tok_add2(&str
, &len
, tok
, tokc
);
811 tok_add(&str
, &len
, -1); /* simulate end of file */
812 tok_add(&str
, &len
, 0);
813 /* now evaluate C constant expression */
823 void tok_print(int *str
)
834 printf(" %s", get_tok_str(t
, c
));
840 /* XXX: should be more factorized */
841 void define_symbol(char *sym
)
846 ts
= tok_alloc(sym
, 0);
849 tok_add2(&str
, &len
, TOK_NUM
, 1);
850 tok_add(&str
, &len
, 0);
851 sym_push1(&define_stack
, ts
->tok
, MACRO_OBJ
, (int)str
);
856 int size
, i
, c
, v
, t
, *str
, len
;
857 char buf
[1024], *q
, *p
;
860 Sym
**ps
, *first
, *s
;
865 if (tok
== TOK_DEFINE
) {
868 /* XXX: should check if same macro (ANSI) */
871 /* '(' must be just after macro definition for MACRO_FUNC */
878 tok
= TOK___VA_ARGS__
;
879 s
= sym_push1(&define_stack
, tok
| SYM_FIELD
, 0, 0);
893 if (ch
== '\n' || ch
== -1)
896 tok_add2(&str
, &len
, tok
, tokc
);
898 tok_add(&str
, &len
, 0);
900 printf("define %s %d: ", get_tok_str(v
, 0), t
);
903 s
= sym_push1(&define_stack
, v
, t
, (int)str
);
905 } else if (tok
== TOK_UNDEF
) {
907 s
= sym_find1(&define_stack
, tok
);
908 /* undefine symbol by putting an invalid name */
910 sym_undef(&define_stack
, s
);
911 } else if (tok
== TOK_INCLUDE
) {
916 } else if (ch
== '\"') {
921 while (ch
!= c
&& ch
!= '\n' && ch
!= -1) {
922 if ((q
- buf
) < sizeof(buf
) - 1)
930 error("#include syntax error");
931 /* XXX: buffer overflow */
932 strcpy(buf
, get_tok_str(tok
, tokc
));
935 if (include_stack_ptr
>= include_stack
+ INCLUDE_STACK_SIZE
)
936 error("memory full");
938 /* first search in current dir if "header.h" */
939 /* XXX: buffer overflow */
941 p
= strrchr(filename
, '/');
943 size
= p
+ 1 - filename
;
944 memcpy(buf1
, filename
, size
);
947 f
= fopen(buf1
, "r");
951 /* now search in standard include path */
952 for(i
=nb_include_paths
- 1;i
>=0;i
--) {
953 strcpy(buf1
, include_paths
[i
]);
956 f
= fopen(buf1
, "r");
960 error("include file '%s' not found", buf1
);
963 /* push current file in stack */
964 /* XXX: fix current line init */
965 include_stack_ptr
->file
= file
;
966 include_stack_ptr
->filename
= filename
;
967 include_stack_ptr
->line_num
= line_num
;
970 filename
= strdup(buf1
);
972 } else if (tok
== TOK_IFNDEF
) {
975 } else if (tok
== TOK_IF
) {
976 c
= expr_preprocess();
978 } else if (tok
== TOK_IFDEF
) {
982 c
= (sym_find1(&define_stack
, tok
) != 0) ^ c
;
984 if (ifdef_stack_ptr
>= ifdef_stack
+ IFDEF_STACK_SIZE
)
985 error("memory full");
986 *ifdef_stack_ptr
++ = c
;
988 } else if (tok
== TOK_ELSE
) {
989 if (ifdef_stack_ptr
== ifdef_stack
||
990 (ifdef_stack_ptr
[-1] & 2))
991 error("#else after #else");
992 c
= (ifdef_stack_ptr
[-1] ^= 3);
994 } else if (tok
== TOK_ELIF
) {
995 if (ifdef_stack_ptr
== ifdef_stack
||
996 ifdef_stack_ptr
[-1] > 1)
997 error("#elif after #else");
998 c
= expr_preprocess();
999 ifdef_stack_ptr
[-1] = c
;
1005 } else if (tok
== TOK_ENDIF
) {
1006 if (ifdef_stack_ptr
== ifdef_stack
)
1009 } else if (tok
== TOK_LINE
) {
1019 /* XXX: potential memory leak */
1020 filename
= strdup(get_tok_str(tok
, tokc
));
1022 } else if (tok
== TOK_ERROR
) {
1025 /* ignore other preprocess commands or #! for C scripts */
1026 while (ch
!= '\n' && ch
!= -1)
1030 /* read a number in base b */
1036 if (ch
>= 'a' & ch
<= 'f')
1038 else if (ch
>= 'A' & ch
<= 'F')
1052 /* read a character for string or char constant and eval escape codes */
1061 /* at most three octal digits */
1065 c
= c
* 8 + ch
- '0';
1068 c
= c
* 8 + ch
- '0';
1073 } else if (ch
== 'x') {
1099 /* return next token without macro substitution */
1100 void next_nomacro1()
1108 while (ch
== '\n') {
1110 while (ch
== ' ' || ch
== 9)
1113 /* preprocessor command if # at start of line after
1118 if (ch
!= ' ' && ch
!= '\t' && ch
!= '\f')
1136 while (isid(ch
) | isnum(ch
)) {
1137 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1138 error("ident too long");
1143 ts
= tok_alloc(token_buf
, q
- token_buf
);
1145 } else if (isnum(ch
)) {
1151 if (ch
== 'x' || ch
== 'X') {
1154 } else if (ch
== 'b' || ch
== 'B') {
1160 /* XXX: add unsigned constant support (ANSI) */
1161 while (ch
== 'L' || ch
== 'l' || ch
== 'U' || ch
== 'u')
1164 } else if (ch
== '\'') {
1172 } else if (ch
== '\"') {
1177 while (ch
!= '\"') {
1180 error("unterminated string");
1181 if (q
>= token_buf
+ STRING_MAX_SIZE
)
1182 error("string too long");
1186 tokc
= (int)tok_alloc(token_buf
, q
- token_buf
);
1189 q
= "<=\236>=\235!=\225&&\240||\241++\244--\242==\224<<\1>>\2+=\253-=\255*=\252/=\257%=\245&=\246^=\336|=\374->\247..\250##\266";
1194 if (*q
== tok
& q
[1] == ch
) {
1197 /* three chars tests */
1198 if (tok
== TOK_SHL
| tok
== TOK_SAR
) {
1203 } else if (tok
== TOK_DOTS
) {
1205 error("parse error");
1212 /* single char substitutions */
1215 else if (tok
== '>')
1220 /* return next token without macro substitution. Can read input from
1228 if (is_long_tok(tok
))
1229 tokc
= *macro_ptr
++;
1236 /* substitute args in macro_str and return allocated string */
1237 int *macro_arg_subst(Sym
**nested_list
, int *macro_str
, Sym
*args
)
1239 int *st
, last_tok
, t
, c
, notfirst
, *str
, len
;
1255 s
= sym_find2(args
, t
);
1257 token_buf
[0] = '\0';
1259 /* XXX: buffer overflow */
1263 strcat(token_buf
, " ");
1268 strcat(token_buf
, get_tok_str(t
, c
));
1272 printf("stringize: %s\n", token_buf
);
1275 ts
= tok_alloc(token_buf
, 0);
1276 tok_add2(&str
, &len
, TOK_STR
, (int)ts
);
1278 tok_add(&str
, &len
, t
);
1280 } else if (is_long_tok(t
)) {
1281 tok_add2(&str
, &len
, t
, *macro_str
++);
1283 s
= sym_find2(args
, t
);
1286 /* if '##' is present before or after , no arg substitution */
1287 if (*macro_str
== TOK_TWOSHARPS
|| last_tok
== TOK_TWOSHARPS
) {
1289 tok_add(&str
, &len
, *st
++);
1291 macro_subst(&str
, &len
, nested_list
, st
);
1294 tok_add(&str
, &len
, t
);
1299 tok_add(&str
, &len
, 0);
1303 /* handle the '##' operator */
1304 int *macro_twosharps(int *macro_str
)
1307 int *macro_str1
, macro_str1_len
, *macro_ptr1
;
1318 if (*macro_ptr
== TOK_TWOSHARPS
) {
1320 macro_ptr1
= macro_ptr
;
1327 /* XXX: we handle only most common cases:
1328 ident + ident or ident + number */
1329 if (tok
>= TOK_IDENT
&&
1330 (t
>= TOK_IDENT
|| t
== TOK_NUM
)) {
1331 /* XXX: buffer overflow */
1332 p
= get_tok_str(tok
, tokc
);
1333 strcpy(token_buf
, p
);
1334 p
= get_tok_str(t
, c
);
1335 strcat(token_buf
, p
);
1336 ts
= tok_alloc(token_buf
, 0);
1337 tok_add2(¯o_str1
, ¯o_str1_len
, ts
->tok
, 0);
1339 /* cannot merge tokens: skip '##' */
1340 macro_ptr
= macro_ptr1
;
1344 tok_add2(¯o_str1
, ¯o_str1_len
, tok
, tokc
);
1347 tok_add(¯o_str1
, ¯o_str1_len
, 0);
1353 /* do macro substitution of macro_str and add result to
1354 (tok_str,tok_len). If macro_str is NULL, then input stream token is
1355 substituted. 'nested_list' is the list of all macros we got inside
1356 to avoid recursing. */
1357 void macro_subst(int **tok_str
, int *tok_len
,
1358 Sym
**nested_list
, int *macro_str
)
1360 Sym
*s
, *args
, *sa
, *sa1
;
1361 int *str
, parlevel
, len
, *mstr
, t
, *saved_macro_ptr
;
1362 int mstr_allocated
, *macro_str1
;
1364 saved_macro_ptr
= macro_ptr
;
1365 macro_ptr
= macro_str
;
1368 /* first scan for '##' operator handling */
1369 macro_str1
= macro_twosharps(macro_str
);
1370 macro_ptr
= macro_str1
;
1377 /* special macros */
1378 if (tok
== TOK___LINE__
) {
1379 tok_add2(tok_str
, tok_len
, TOK_NUM
, line_num
);
1380 } else if (tok
== TOK___FILE__
) {
1381 tok_add2(tok_str
, tok_len
, TOK_STR
,
1382 (int)tok_alloc(filename
, 0));
1383 } else if (tok
== TOK___DATE__
) {
1384 tok_add2(tok_str
, tok_len
, TOK_STR
,
1385 (int)tok_alloc("Jan 1 1970", 0));
1386 } else if (tok
== TOK___TIME__
) {
1387 tok_add2(tok_str
, tok_len
, TOK_STR
,
1388 (int)tok_alloc("00:00:00", 0));
1389 } else if ((s
= sym_find1(&define_stack
, tok
)) != NULL
) {
1390 /* if symbol is a macro, prepare substitution */
1391 /* if nested substitution, do nothing */
1392 if (sym_find2(*nested_list
, tok
))
1396 if (s
->t
== MACRO_FUNC
) {
1397 /* NOTE: we do not use next_nomacro to avoid eating the
1398 next token. XXX: find better solution */
1402 while (ch
== ' ' || ch
== '\t' || ch
== '\n')
1406 if (t
!= '(') /* no macro subst */
1409 /* argument macro */
1414 while (tok
!= ')' && sa
) {
1418 while ((parlevel
> 0 ||
1421 sa
->v
== (TOK___VA_ARGS__
| SYM_FIELD
)))) &&
1425 else if (tok
== ')')
1427 tok_add2(&str
, &len
, tok
, tokc
);
1430 tok_add(&str
, &len
, 0);
1431 sym_push2(&args
, sa
->v
& ~SYM_FIELD
, 0, (int)str
);
1439 /* now subst each arg */
1440 mstr
= macro_arg_subst(nested_list
, mstr
, args
);
1451 sym_push2(nested_list
, s
->v
, 0, 0);
1452 macro_subst(tok_str
, tok_len
, nested_list
, mstr
);
1453 /* pop nested defined symbol */
1455 *nested_list
= sa1
->prev
;
1461 /* no need to add if reading input stream */
1464 tok_add2(tok_str
, tok_len
, tok
, tokc
);
1466 /* only replace one macro while parsing input stream */
1470 macro_ptr
= saved_macro_ptr
;
1475 /* return next token with macro substitution */
1481 /* special 'ungettok' case for label parsing */
1489 /* if not reading from macro substuted string, then try to substitute */
1493 macro_subst(&ptr
, &len
, &nested_list
, NULL
);
1495 tok_add(&ptr
, &len
, 0);
1497 macro_ptr_allocated
= ptr
;
1505 /* end of macro string: free it */
1506 free(macro_ptr_allocated
);
1513 printf("token = %s\n", get_tok_str(tok
, tokc
));
1517 void swap(int *p
, int *q
)
1531 /******************************************************/
1532 /* X86 code generator */
1534 typedef struct GFuncContext
{
1551 void gen_le32(int c
)
1559 /* add a new relocation entry to symbol 's' */
1560 void greloc(Sym
*s
, int addr
, int type
)
1563 p
= malloc(sizeof(Reloc
));
1565 error("memory full");
1568 p
->next
= (Reloc
*)s
->c
;
1572 /* patch each relocation entry with value 'val' */
1573 void greloc_patch(Sym
*s
, int val
)
1582 *(int *)p
->addr
= val
;
1585 *(int *)p
->addr
= val
- p
->addr
- 4;
1592 s
->t
&= ~VT_FORWARD
;
1595 /* output a symbol and patch all calls to it */
1596 void gsym_addr(t
, a
)
1600 n
= *(int *)t
; /* next value */
1601 *(int *)t
= a
- t
- 4;
1611 /* psym is used to put an instruction with a data field which is a
1612 reference to a symbol. It is in fact the same as oad ! */
1615 /* instruction + 4 bytes data. Return the address of the data */
1616 int oad(int c
, int s
)
1625 /* output constant with relocation if 't & VT_FORWARD' is true */
1626 void gen_addr32(int c
, int t
)
1628 if (!(t
& VT_FORWARD
)) {
1631 greloc((Sym
*)c
, ind
, RELOC_ADDR32
);
1636 /* XXX: generate correct pointer for forward references to functions */
1638 void load(r
, ft
, fc
)
1642 v
= ft
& VT_VALMASK
;
1644 if (v
== VT_LLOCAL
) {
1645 load(r
, VT_LOCAL
| VT_LVAL
, fc
);
1648 if ((ft
& VT_TYPE
) == VT_BYTE
)
1649 o(0xbe0f); /* movsbl */
1650 else if ((ft
& VT_TYPE
) == (VT_BYTE
| VT_UNSIGNED
))
1651 o(0xb60f); /* movzbl */
1652 else if ((ft
& VT_TYPE
) == VT_SHORT
)
1653 o(0xbf0f); /* movswl */
1654 else if ((ft
& VT_TYPE
) == (VT_SHORT
| VT_UNSIGNED
))
1655 o(0xb70f); /* movzwl */
1658 if (v
== VT_CONST
) {
1659 o(0x05 + r
* 8); /* 0xXX, r */
1661 } else if (v
== VT_LOCAL
) {
1662 oad(0x85 + r
* 8, fc
); /* xx(%ebp), r */
1664 g(0x00 + r
* 8 + v
); /* (v), r */
1667 if (v
== VT_CONST
) {
1668 o(0xb8 + r
); /* mov $xx, r */
1670 } else if (v
== VT_LOCAL
) {
1672 oad(0x85 + r
* 8, fc
); /* lea xxx(%ebp), r */
1673 } else if (v
== VT_CMP
) {
1674 oad(0xb8 + r
, 0); /* mov $0, r */
1675 o(0x0f); /* setxx %br */
1678 } else if (v
== VT_JMP
|| v
== VT_JMPI
) {
1680 oad(0xb8 + r
, t
); /* mov $1, r */
1681 oad(0xe9, 5); /* jmp after */
1683 oad(0xb8 + r
, t
^ 1); /* mov $0, r */
1684 } else if (v
!= r
) {
1686 o(0xc0 + r
+ v
* 8); /* mov v, r */
1692 /* WARNING: r must not be allocated on the stack */
1693 void store(r
, ft
, fc
)
1697 fr
= ft
& VT_VALMASK
;
1699 /* XXX: incorrect if reg to reg */
1706 if (fr
== VT_CONST
) {
1707 o(0x05 + r
* 8); /* mov r,xxx */
1709 } else if (fr
== VT_LOCAL
) {
1710 oad(0x85 + r
* 8, fc
); /* mov r,xxx(%ebp) */
1711 } else if (ft
& VT_LVAL
) {
1712 g(fr
+ r
* 8); /* mov r, (fr) */
1713 } else if (fr
!= r
) {
1714 o(0xc0 + fr
+ r
* 8); /* mov r, fr */
1718 /* start function call and return function call context */
1719 void gfunc_start(GFuncContext
*c
)
1724 /* push function parameter which is in (vt, vc) */
1725 void gfunc_param(GFuncContext
*c
)
1727 int size
, align
, ft
, fc
, r
;
1729 if ((vt
& (VT_BTYPE
| VT_LVAL
)) == (VT_STRUCT
| VT_LVAL
)) {
1730 size
= type_size(vt
, &align
);
1731 /* align to stack align size */
1732 size
= (size
+ 3) & ~3;
1733 /* allocate the necessary size on stack */
1734 oad(0xec81, size
); /* sub $xxx, %esp */
1735 /* generate structure store */
1737 o(0x89); /* mov %esp, r */
1741 vset(VT_INT
| r
, 0);
1746 c
->args_size
+= size
;
1748 /* simple type (currently always same size) */
1749 /* XXX: implicit cast ? */
1751 o(0x50 + r
); /* push r */
1756 /* generate function call with address in (vt, vc) and free function
1758 void gfunc_call(GFuncContext
*c
)
1761 if ((vt
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
1763 /* forward reference */
1764 if (vt
& VT_FORWARD
) {
1765 greloc((Sym
*)vc
, ind
+ 1, RELOC_REL32
);
1768 oad(0xe8, vc
- ind
- 5);
1771 /* otherwise, indirect call */
1773 o(0xff); /* call *r */
1777 oad(0xc481, c
->args_size
); /* add $xxx, %esp */
1782 return psym(0xe9, t
);
1785 /* generate a test. set 'inv' to invert test */
1786 int gtst(int inv
, int t
)
1789 v
= vt
& VT_VALMASK
;
1791 /* fast case : can jump directly since flags are set */
1793 t
= psym((vc
- 16) ^ inv
, t
);
1794 } else if (v
== VT_JMP
|| v
== VT_JMPI
) {
1795 /* && or || optimization */
1796 if ((v
& 1) == inv
) {
1797 /* insert vc jump list in t */
1807 } else if ((vt
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
) {
1808 /* constant jmp optimization */
1809 if ((vc
!= 0) != inv
)
1816 t
= psym(0x85 ^ inv
, t
);
1821 /* generate a binary operation 'v = r op fr' instruction and modifies
1822 (vt,vc) if needed */
1823 void gen_op1(int op
, int r
, int fr
)
1828 o(0xc0 + r
+ fr
* 8);
1829 } else if (op
== '-') {
1831 o(0xc0 + r
+ fr
* 8);
1832 } else if (op
== '&') {
1834 o(0xc0 + r
+ fr
* 8);
1835 } else if (op
== '^') {
1837 o(0xc0 + r
+ fr
* 8);
1838 } else if (op
== '|') {
1840 o(0xc0 + r
+ fr
* 8);
1841 } else if (op
== '*') {
1842 o(0xaf0f); /* imul fr, r */
1843 o(0xc0 + fr
+ r
* 8);
1844 } else if (op
== TOK_SHL
| op
== TOK_SHR
| op
== TOK_SAR
) {
1850 o(0x87); /* xchg r, %ecx */
1855 o(0xd3); /* shl/shr/sar %cl, r */
1858 else if (op
== TOK_SHR
)
1862 vt
= (vt
& VT_TYPE
) | r
;
1863 } else if (op
== '/' | op
== TOK_UDIV
| op
== TOK_PDIV
|
1864 op
== '%' | op
== TOK_UMOD
) {
1865 save_reg(2); /* save edx */
1866 t
= save_reg_forced(fr
); /* save fr and get op2 location */
1867 move_reg(0, r
); /* op1 is %eax */
1868 if (op
== TOK_UDIV
| op
== TOK_UMOD
) {
1869 o(0xf7d231); /* xor %edx, %edx, div t(%ebp), %eax */
1872 o(0xf799); /* cltd, idiv t(%ebp), %eax */
1875 if (op
== '%' | op
== TOK_UMOD
)
1879 vt
= (vt
& VT_TYPE
) | r
;
1882 o(0xc0 + r
+ fr
* 8); /* cmp fr, r */
1887 /* end of X86 code generator */
1888 /*************************************************************/
1890 int save_reg_forced(int r
)
1893 /* store register */
1894 loc
= (loc
- 4) & -3;
1895 store(r
, VT_LOCAL
, loc
);
1898 /* modify all stack values */
1899 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1900 i
= p
[0] & VT_VALMASK
;
1906 p
[0] = (p
[0] & VT_TYPE
) | VT_LVAL
| t
;
1913 /* save r to memory. and mark it as being free */
1918 /* modify all stack values */
1919 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1920 i
= p
[0] & VT_VALMASK
;
1928 /* find a free register. If none, save one register */
1933 /* find a free register */
1934 for(r
=0;r
<NB_REGS
;r
++) {
1935 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1936 i
= p
[0] & VT_VALMASK
;
1944 /* no register left : free the first one on the stack (very
1945 important to start from the bottom to ensure that we don't
1946 spill registers used in gen_op()) */
1947 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1948 r
= p
[0] & VT_VALMASK
;
1960 for(p
=vstack
;p
<vstack_ptr
;p
+=2) {
1961 r
= p
[0] & VT_VALMASK
;
1968 /* move register 's' to 'r', and flush previous value of r to memory
1978 /* convert a stack entry in register. lvalues are converted as
1979 values. Cannot be used if cannot be converted to register value
1980 (such as structures). */
1984 r
= p
[0] & VT_VALMASK
;
1985 if (r
>= VT_CONST
|| (p
[0] & VT_LVAL
))
1987 /* NOTE: get_reg can modify p[] */
1988 load(r
, p
[0], p
[1]);
1989 p
[0] = (p
[0] & VT_TYPE
) | r
;
1995 if (vstack_ptr
>= vstack
+ VSTACK_SIZE
)
1996 error("memory full");
1999 /* cannot let cpu flags if other instruction are generated */
2000 /* XXX: VT_JMP test too ? */
2001 if ((vt
& VT_VALMASK
) == VT_CMP
)
2002 gvp(vstack_ptr
- 2);
2005 void vpop(int *ft
, int *fc
)
2007 *fc
= *--vstack_ptr
;
2008 *ft
= *--vstack_ptr
;
2011 /* generate a value in a register from vt and vc */
2016 r
= gvp(vstack_ptr
- 2);
2021 /* handle constant optimizations and various machine independant opt */
2024 int fr
, ft
, fc
, r
, c1
, c2
, n
;
2028 c1
= (vt
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
;
2029 c2
= (ft
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
;
2032 case '+': vc
+= fc
; break;
2033 case '-': vc
-= fc
; break;
2034 case '&': vc
&= fc
; break;
2035 case '^': vc
^= fc
; break;
2036 case '|': vc
|= fc
; break;
2037 case '*': vc
*= fc
; break;
2039 case '/': vc
/= fc
; break; /* XXX: zero case ? */
2040 case '%': vc
%= fc
; break; /* XXX: zero case ? */
2041 case TOK_UDIV
: vc
= (unsigned)vc
/ fc
; break; /* XXX: zero case ? */
2042 case TOK_UMOD
: vc
= (unsigned)vc
% fc
; break; /* XXX: zero case ? */
2043 case TOK_SHL
: vc
<<= fc
; break;
2044 case TOK_SHR
: vc
= (unsigned)vc
>> fc
; break;
2045 case TOK_SAR
: vc
>>= fc
; break;
2047 case TOK_ULT
: vc
= (unsigned)vc
< (unsigned)fc
; break;
2048 case TOK_UGE
: vc
= (unsigned)vc
>= (unsigned)fc
; break;
2049 case TOK_EQ
: vc
= vc
== fc
; break;
2050 case TOK_NE
: vc
= vc
!= fc
; break;
2051 case TOK_ULE
: vc
= (unsigned)vc
<= (unsigned)fc
; break;
2052 case TOK_UGT
: vc
= (unsigned)vc
> (unsigned)fc
; break;
2053 case TOK_LT
: vc
= vc
< fc
; break;
2054 case TOK_GE
: vc
= vc
>= fc
; break;
2055 case TOK_LE
: vc
= vc
<= fc
; break;
2056 case TOK_GT
: vc
= vc
> fc
; break;
2058 case TOK_LAND
: vc
= vc
&& fc
; break;
2059 case TOK_LOR
: vc
= vc
|| fc
; break;
2064 /* if commutative ops, put c2 as constant */
2065 if (c1
&& (op
== '+' || op
== '&' || op
== '^' ||
2066 op
== '|' || op
== '*')) {
2071 if (c2
&& (((op
== '*' || op
== '/' || op
== TOK_UDIV
||
2074 ((op
== '+' || op
== '-' || op
== '|' || op
== '^' ||
2075 op
== TOK_SHL
|| op
== TOK_SHR
|| op
== TOK_SAR
) &&
2079 } else if (c2
&& (op
== '*' || op
== TOK_PDIV
|| op
== TOK_UDIV
)) {
2080 /* try to use shifts instead of muls or divs */
2081 if (fc
> 0 && (fc
& (fc
- 1)) == 0) {
2090 else if (op
== TOK_PDIV
)
2102 r
= gvp(vstack_ptr
- 4);
2103 fr
= gvp(vstack_ptr
- 2);
2106 /* call low level op generator */
2112 int pointed_size(int t
)
2114 return type_size(pointed_type(t
), &t
);
2117 /* generic gen_op: handles types problems */
2123 t1
= vstack_ptr
[-4];
2124 t2
= vstack_ptr
[-2];
2125 if (op
== '+' | op
== '-') {
2126 if ((t1
& VT_BTYPE
) == VT_PTR
&&
2127 (t2
& VT_BTYPE
) == VT_PTR
) {
2129 error("invalid type");
2130 /* XXX: check that types are compatible */
2131 u
= pointed_size(t1
);
2134 vstack_ptr
[-2] &= ~VT_TYPE
; /* set to integer */
2137 } else if ((t1
& VT_BTYPE
) == VT_PTR
||
2138 (t2
& VT_BTYPE
) == VT_PTR
) {
2139 if ((t2
& VT_BTYPE
) == VT_PTR
) {
2140 swap(vstack_ptr
- 4, vstack_ptr
- 2);
2141 swap(vstack_ptr
- 3, vstack_ptr
- 1);
2144 /* stack-4 contains pointer, stack-2 value to add */
2145 vset(VT_CONST
, pointed_size(vstack_ptr
[-4]));
2149 /* put again type if gen_opc() swaped operands */
2150 vt
= (vt
& ~VT_TYPE
) | (t1
& VT_TYPE
);
2155 /* XXX: test types and compute returned value */
2156 if ((t1
| t2
) & VT_UNSIGNED
||
2157 (t1
& VT_BTYPE
) == VT_PTR
||
2158 (t2
& VT_BTYPE
) == VT_PTR
) {
2165 else if (op
== TOK_LT
)
2167 else if (op
== TOK_GT
)
2169 else if (op
== TOK_LE
)
2171 else if (op
== TOK_GE
)
2178 /* cast (vt, vc) to 't' type */
2179 void gen_cast(int t
)
2182 r
= vt
& VT_VALMASK
;
2183 if (!(t
& VT_LVAL
)) {
2184 /* if not lvalue, then we convert now */
2185 if ((t
& VT_TYPE
& ~VT_UNSIGNED
) == VT_BYTE
)
2187 else if ((t
& VT_TYPE
& ~VT_UNSIGNED
) == VT_SHORT
)
2192 if (t
& VT_UNSIGNED
) {
2193 vset(VT_CONST
, (1 << bits
) - 1);
2197 vset(VT_CONST
, bits
);
2200 vset(VT_CONST
, bits
);
2205 vt
= (vt
& ~VT_TYPE
) | t
;
2208 /* return type size. Put alignment at 'a' */
2209 int type_size(int t
, int *a
)
2215 if (bt
== VT_STRUCT
) {
2217 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
2218 *a
= 4; /* XXX: cannot store it yet. Doing that is safe */
2220 } else if (t
& VT_ARRAY
) {
2221 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
2222 return type_size(s
->t
, a
) * s
->c
;
2223 } else if (bt
== VT_PTR
||
2228 } else if (bt
== VT_SHORT
) {
2232 /* void or function */
2238 /* return the pointed type of t */
2239 int pointed_type(int t
)
2242 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
2243 return s
->t
| (t
& ~VT_TYPE
);
2246 int mk_pointer(int t
)
2251 return VT_PTR
| (p
<< VT_STRUCT_SHIFT
) | (t
& ~VT_TYPE
);
2254 /* store value in lvalue pushed on stack */
2257 int ft
, fc
, r
, t
, size
, align
;
2260 if ((vt
& VT_BTYPE
) == VT_STRUCT
) {
2261 /* if structure, only generate pointer */
2262 /* structure assignment : generate memcpy */
2263 /* XXX: optimize if small size */
2269 size
= type_size(vt
, &align
);
2270 vset(VT_CONST
, size
);
2282 vset(VT_CONST
, (int)&memcpy
);
2285 /* generate again current type */
2289 r
= gv(); /* generate value */
2291 ft
= vstack_ptr
[-4];
2292 fc
= vstack_ptr
[-3];
2293 /* if lvalue was saved on stack, must read it */
2294 if ((ft
& VT_VALMASK
) == VT_LLOCAL
) {
2296 load(t
, VT_LOCAL
| VT_LVAL
, fc
);
2297 ft
= (ft
& ~VT_VALMASK
) | t
;
2304 /* post defines POST/PRE add. c is the token ++ or -- */
2310 vpush(); /* room for returned value */
2311 vpush(); /* save lvalue */
2313 vpush(); /* save value */
2315 /* duplicate value */
2317 load(r1
, r
, 0); /* move r to r1 */
2318 vstack_ptr
[-6] = (vt
& VT_TYPE
) | r1
;
2322 vset(VT_CONST
, c
- TOK_MID
);
2324 vstore(); /* store value */
2329 /* enum/struct/union declaration */
2330 int struct_decl(int u
)
2332 int a
, t
, b
, v
, size
, align
, maxalign
, c
;
2335 a
= tok
; /* save decl type */
2340 /* struct already defined ? return it */
2341 /* XXX: check consistency */
2342 if (s
= sym_find(v
| SYM_STRUCT
)) {
2344 error("invalid type");
2350 s
= sym_push(v
| SYM_STRUCT
, a
, 0);
2351 /* put struct/union/enum name in type */
2353 u
= u
| (v
<< VT_STRUCT_SHIFT
);
2358 error("struct/union/enum already defined");
2359 /* cannot be empty */
2364 if (a
== TOK_ENUM
) {
2371 /* enum symbols have static storage */
2372 sym_push(v
, VT_CONST
| VT_STATIC
, c
);
2379 t
= type_decl(&v
, b
, TYPE_DIRECT
);
2380 if ((t
& VT_BTYPE
) == VT_FUNC
||
2381 (t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
)))
2382 error("invalid type");
2383 /* XXX: align & correct type size */
2385 size
= type_size(t
, &align
);
2386 if (a
== TOK_STRUCT
) {
2387 c
= (c
+ align
- 1) & -align
;
2388 ss
= sym_push(v
, t
, c
);
2391 ss
= sym_push(v
, t
, 0);
2395 if (align
> maxalign
)
2399 if (tok
== ';' || tok
== -1)
2409 /* size for struct/union, dummy for enum */
2410 s
->c
= (c
+ maxalign
- 1) & -maxalign
;
2415 /* return 0 if no type declaration. otherwise, return the basic type
2417 XXX: A '2' is ored to ensure non zero return if int type.
2433 if ((t
& VT_BTYPE
) != 0)
2434 error("too many basic types %x", t
);
2447 /* XXX: add long type */
2452 /* XXX: add float types */
2456 u
= struct_decl(VT_ENUM
);
2460 u
= struct_decl(VT_STRUCT
);
2463 /* type modifiers */
2493 if (!s
|| !(s
->t
& VT_TYPEDEF
))
2495 t
|= (s
->t
& ~VT_TYPEDEF
);
2505 int post_type(int t
)
2507 int p
, n
, pt
, l
, t1
;
2508 Sym
**plast
, *s
, *first
;
2511 /* function declaration */
2516 while (tok
!= ')') {
2517 /* read param name and compute offset */
2518 if (l
!= FUNC_OLD
) {
2519 if (!(pt
= ist())) {
2521 error("invalid type");
2527 if ((pt
& VT_BTYPE
) == VT_VOID
&& tok
== ')')
2530 pt
= type_decl(&n
, pt
, TYPE_DIRECT
| TYPE_ABSTRACT
);
2537 /* array must be transformed to pointer according to ANSI C */
2539 s
= sym_push(n
| SYM_FIELD
, pt
, 0);
2544 if (l
== FUNC_NEW
&& tok
== TOK_DOTS
) {
2552 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
2553 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
));
2554 /* we push a anonymous symbol which will contain the function prototype */
2556 s
= sym_push(p
, t
, l
);
2558 t
= t1
| VT_FUNC
| (p
<< VT_STRUCT_SHIFT
);
2559 } else if (tok
== '[') {
2560 /* array definition */
2566 error("invalid array size");
2569 /* parse next post type */
2570 t1
= t
& (VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
);
2571 t
= post_type(t
& ~(VT_TYPEDEF
| VT_STATIC
| VT_EXTERN
));
2573 /* we push a anonymous symbol which will contain the array
2577 t
= t1
| VT_ARRAY
| VT_PTR
| (p
<< VT_STRUCT_SHIFT
);
2582 /* Read a type declaration (except basic type), and return the
2583 type. If v is true, then also put variable name in 'vc' */
2584 int type_decl(int *v
, int t
, int td
)
2589 t
= t
& -3; /* suppress the ored '2' */
2590 while (tok
== '*') {
2592 while (tok
== TOK_CONST
|| tok
== TOK_VOLATILE
|| tok
== TOK_RESTRICT
)
2597 /* recursive type */
2598 /* XXX: incorrect if abstract type for functions (e.g. 'int ()') */
2601 u
= type_decl(v
, 0, td
);
2605 /* type identifier */
2606 if (tok
>= TOK_IDENT
&& (td
& TYPE_DIRECT
)) {
2610 if (!(td
& TYPE_ABSTRACT
))
2611 expect("identifier");
2615 /* append t at the end of u */
2621 s
= sym_find((unsigned)p
>> VT_STRUCT_SHIFT
);
2631 /* define a new external reference to a function 'v' of type 'u' */
2632 Sym
*external_sym(int v
, int u
)
2637 /* push forward reference */
2638 s
= sym_push1(&global_stack
,
2639 v
, u
| VT_CONST
| VT_FORWARD
, 0);
2648 if ((vt
& VT_BTYPE
) != VT_PTR
)
2650 vt
= pointed_type(vt
);
2651 if (!(vt
& VT_ARRAY
)) /* an array is never an lvalue */
2657 int n
, t
, ft
, fc
, p
, align
, size
;
2661 if (tok
== TOK_NUM
|| tok
== TOK_CCHAR
|| tok
== TOK_LCHAR
) {
2662 vset(VT_CONST
, tokc
);
2664 } else if (tok
== TOK___FUNC__
) {
2665 /* special function name identifier */
2666 /* generate (char *) type */
2667 vset(VT_CONST
| mk_pointer(VT_BYTE
), glo
);
2668 strcpy((void *)glo
, funcname
);
2669 glo
+= strlen(funcname
) + 1;
2671 } else if (tok
== TOK_LSTR
) {
2674 } else if (tok
== TOK_STR
) {
2675 /* string parsing */
2678 type_size(t
, &align
);
2679 glo
= (glo
+ align
- 1) & -align
;
2681 /* we must declare it as an array first to use initializer parser */
2682 t
= VT_CONST
| VT_ARRAY
| mk_pointer(t
);
2683 decl_initializer(t
, glo
, 1, 0);
2684 glo
+= type_size(t
, &align
);
2685 /* put it as pointer */
2686 vset(t
& ~VT_ARRAY
, fc
);
2693 ft
= type_decl(&n
, t
, TYPE_ABSTRACT
);
2695 /* check ISOC99 compound literal */
2697 /* data is allocated locally by default */
2702 /* all except arrays are lvalues */
2703 if (!(ft
& VT_ARRAY
))
2705 fc
= decl_initializer_alloc(ft
, 1);
2715 } else if (t
== '*') {
2718 } else if (t
== '&') {
2720 /* functions names must be treated as function pointers,
2721 except for unary '&' and sizeof. Since we consider that
2722 functions are not lvalues, we only have to handle it
2723 there and in function calls. */
2724 if ((vt
& VT_BTYPE
) != VT_FUNC
)
2726 vt
= mk_pointer(vt
& VT_LVALN
);
2730 if ((vt
& (VT_VALMASK
| VT_LVAL
)) == VT_CONST
)
2732 else if ((vt
& VT_VALMASK
) == VT_CMP
)
2735 vset(VT_JMP
, gtst(1, 0));
2746 if (t
== TOK_SIZEOF
) {
2747 /* XXX: some code can be generated */
2751 vt
= type_decl(&n
, t
, TYPE_ABSTRACT
);
2758 vset(VT_CONST
, type_size(vt
, &t
));
2760 if (t
== TOK_INC
| t
== TOK_DEC
) {
2763 } else if (t
== '-') {
2773 error("'%s' undeclared", get_tok_str(t
, 0));
2774 /* for simple function calls, we tolerate undeclared
2775 external reference */
2777 sym_push1(&global_stack
, p
, 0, FUNC_OLD
);
2778 /* int() function */
2779 s
= external_sym(t
, VT_FUNC
| (p
<< VT_STRUCT_SHIFT
));
2782 /* if forward reference, we must point to s */
2783 if (vt
& VT_FORWARD
)
2788 /* post operations */
2790 if (tok
== TOK_INC
| tok
== TOK_DEC
) {
2793 } else if (tok
== '.' | tok
== TOK_ARROW
) {
2795 if (tok
== TOK_ARROW
)
2800 /* expect pointer on structure */
2801 if ((vt
& VT_BTYPE
) != VT_STRUCT
)
2802 expect("struct or union");
2803 s
= sym_find(((unsigned)vt
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
2806 while (s
= s
->next
) {
2811 error("field not found");
2812 /* add field offset to pointer */
2813 vt
= (vt
& ~VT_TYPE
) | VT_INT
; /* change type to int */
2815 vset(VT_CONST
, s
->c
);
2817 /* change type to field type, and set to lvalue */
2818 vt
= (vt
& ~VT_TYPE
) | s
->t
;
2819 /* an array is never an lvalue */
2820 if (!(vt
& VT_ARRAY
))
2823 } else if (tok
== '[') {
2830 } else if (tok
== '(') {
2834 if ((vt
& VT_BTYPE
) != VT_FUNC
) {
2835 /* pointer test (no array accepted) */
2836 if ((vt
& (VT_BTYPE
| VT_ARRAY
)) == VT_PTR
) {
2837 vt
= pointed_type(vt
);
2838 if ((vt
& VT_BTYPE
) != VT_FUNC
)
2842 expect("function pointer");
2845 vt
&= ~VT_LVAL
; /* no lvalue */
2848 /* get return type */
2849 s
= sym_find((unsigned)vt
>> VT_STRUCT_SHIFT
);
2850 vpush(); /* push function address */
2851 save_regs(); /* save used temporary registers */
2854 #ifdef INVERT_FUNC_PARAMS
2856 int *str
, len
, parlevel
, *saved_macro_ptr
;
2859 /* read each argument and store it on a stack */
2860 /* XXX: merge it with macro args ? */
2862 while (tok
!= ')') {
2866 while ((parlevel
> 0 || (tok
!= ')' && tok
!= ',')) &&
2870 else if (tok
== ')')
2872 tok_add2(&str
, &len
, tok
, tokc
);
2875 tok_add(&str
, &len
, -1); /* end of file added */
2876 tok_add(&str
, &len
, 0);
2877 sym_push2(&args
, 0, 0, (int)str
);
2885 /* now generate code in reverse order by reading the stack */
2886 saved_macro_ptr
= macro_ptr
;
2888 macro_ptr
= (int *)args
->c
;
2892 expect("',' or ')'");
2895 free((int *)args
->c
);
2899 macro_ptr
= saved_macro_ptr
;
2904 /* compute first implicit argument if a structure is returned */
2905 if ((s
->t
& VT_BTYPE
) == VT_STRUCT
) {
2906 /* get some space for the returned structure */
2907 size
= type_size(s
->t
, &align
);
2908 loc
= (loc
- size
) & -align
;
2909 rett
= s
->t
| VT_LOCAL
| VT_LVAL
;
2910 /* pass it as 'int' to avoid structure arg passing
2912 vset(VT_INT
| VT_LOCAL
, loc
);
2916 rett
= s
->t
| FUNC_RET_REG
; /* return in register */
2919 #ifndef INVERT_FUNC_PARAMS
2920 while (tok
!= ')') {
2939 int is_compatible_types(int t1
, int t2
)
2946 bt1
= t1
& VT_BTYPE
;
2947 bt2
= t2
& VT_BTYPE
;
2948 if (bt1
== VT_PTR
) {
2949 t1
= pointed_type(t1
);
2950 /* if function, then convert implictely to function pointer */
2951 if (bt2
!= VT_FUNC
) {
2954 t2
= pointed_type(t2
);
2956 /* void matches everything */
2959 if (t1
== VT_VOID
|| t2
== VT_VOID
)
2961 return is_compatible_types(t1
, t2
);
2962 } else if (bt1
== VT_STRUCT
) {
2964 } else if (bt1
== VT_FUNC
) {
2967 s1
= sym_find(((unsigned)t1
>> VT_STRUCT_SHIFT
));
2968 s2
= sym_find(((unsigned)t2
>> VT_STRUCT_SHIFT
));
2969 if (!is_compatible_types(s1
->t
, s2
->t
))
2971 /* XXX: not complete */
2972 if (s1
->c
== FUNC_OLD
|| s2
->c
== FUNC_OLD
)
2976 while (s1
!= NULL
) {
2979 if (!is_compatible_types(s1
->t
, s2
->t
))
2988 /* XXX: not complete */
2993 int check_assign_types(int t1
, int t2
)
2997 if ((t1
& VT_BTYPE
) == VT_PTR
&&
2998 (t2
& VT_BTYPE
) == VT_FUNC
) {
2999 return is_compatible_types(pointed_type(t1
), t2
);
3001 return is_compatible_types(t1
, t2
);
3012 (tok
>= TOK_A_MOD
& tok
<= TOK_A_DIV
) |
3013 tok
== TOK_A_XOR
| tok
== TOK_A_OR
|
3014 tok
== TOK_A_SHL
| tok
== TOK_A_SAR
) {
3021 if (!check_assign_types(vstack_ptr
[-2], vt
))
3022 warning("incompatible types");
3040 while ((l
== 0 & (tok
== '*' | tok
== '/' | tok
== '%')) |
3041 (l
== 1 & (tok
== '+' | tok
== '-')) |
3042 (l
== 2 & (tok
== TOK_SHL
| tok
== TOK_SAR
)) |
3043 (l
== 3 & ((tok
>= TOK_ULE
& tok
<= TOK_GT
) |
3044 tok
== TOK_ULT
| tok
== TOK_UGE
)) |
3045 (l
== 4 & (tok
== TOK_EQ
| tok
== TOK_NE
)) |
3046 (l
== 5 & tok
== '&') |
3047 (l
== 6 & tok
== '^') |
3048 (l
== 7 & tok
== '|') |
3049 (l
== 8 & tok
== TOK_LAND
) |
3050 (l
== 9 & tok
== TOK_LOR
)) {
3060 /* only used if non constant */
3068 if (tok
!= TOK_LAND
) {
3088 if (tok
!= TOK_LOR
) {
3101 /* XXX: better constant handling */
3104 int t
, u
, c
, r1
, r2
;
3131 vt
= (vt
& VT_TYPE
) | r1
;
3153 if ((vt
& (VT_CONST
| VT_LVAL
)) != VT_CONST
)
3159 /* return the label token if current token is a label, otherwise
3165 /* fast test first */
3166 if (tok
< TOK_UIDENT
)
3175 /* XXX: may not work in all cases (macros ?) */
3184 void block(int *bsym
, int *csym
, int *case_sym
, int *def_sym
, int case_reg
)
3189 if (tok
== TOK_IF
) {
3196 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3198 if (c
== TOK_ELSE
) {
3202 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3203 gsym(d
); /* patch else jmp */
3206 } else if (tok
== TOK_WHILE
) {
3214 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
3215 oad(0xe9, d
- ind
- 5); /* jmp */
3218 } else if (tok
== '{') {
3221 s
= local_stack
.top
;
3222 while (tok
!= '}') {
3225 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3227 /* pop locally defined symbols */
3228 sym_pop(&local_stack
, s
);
3230 } else if (tok
== TOK_RETURN
) {
3233 if ((func_vt
& VT_BTYPE
) == VT_STRUCT
) {
3234 /* if returning structure, must copy it to implicit
3235 first pointer arg location */
3236 vset(mk_pointer(func_vt
) | VT_LOCAL
| VT_LVAL
, func_vc
);
3241 if ((func_vt
& VT_BTYPE
) == VT_STRUCT
) {
3242 /* copy structure value to pointer */
3245 /* move return value to standard return register */
3246 move_reg(FUNC_RET_REG
, gv());
3250 rsym
= gjmp(rsym
); /* jmp */
3251 } else if (tok
== TOK_BREAK
) {
3254 error("cannot break");
3255 *bsym
= gjmp(*bsym
);
3258 } else if (tok
== TOK_CONTINUE
) {
3261 error("cannot continue");
3262 *csym
= gjmp(*csym
);
3265 } else if (tok
== TOK_FOR
) {
3285 oad(0xe9, d
- ind
- 5); /* jmp */
3289 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
3290 oad(0xe9, c
- ind
- 5); /* jmp */
3294 if (tok
== TOK_DO
) {
3299 block(&a
, &b
, case_sym
, def_sym
, case_reg
);
3310 if (tok
== TOK_SWITCH
) {
3317 b
= gjmp(0); /* jump to first case */
3319 block(&a
, csym
, &b
, &c
, case_reg
);
3320 /* if no default, jmp after switch */
3328 if (tok
== TOK_CASE
) {
3333 /* since a case is like a label, we must skip it with a jmp */
3340 *case_sym
= gtst(1, 0);
3343 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3345 if (tok
== TOK_DEFAULT
) {
3351 error("too many 'default'");
3353 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3355 if (tok
== TOK_GOTO
) {
3357 s
= sym_find1(&label_stack
, tok
);
3358 /* put forward definition if needed */
3360 s
= sym_push1(&label_stack
, tok
, VT_FORWARD
, 0);
3361 /* label already defined */
3362 if (s
->t
& VT_FORWARD
)
3363 s
->c
= gjmp(s
->c
); /* jmp xxx */
3365 oad(0xe9, s
->c
- ind
- 5); /* jmp xxx */
3372 s
= sym_find1(&label_stack
, b
);
3374 if (!(s
->t
& VT_FORWARD
))
3375 error("multiple defined label");
3380 sym_push1(&label_stack
, b
, 0, ind
);
3382 /* we accept this, but it is a mistake */
3384 warning("deprecated use of label at end of compound statement");
3386 block(bsym
, csym
, case_sym
, def_sym
, case_reg
);
3388 /* expression case */
3397 /* t is the array or struct type. c is the array or struct
3398 address. cur_index/cur_field is the pointer to the current
3399 value. 'size_only' is true if only size info is needed (only used
3401 void decl_designator(int t
, int c
,
3402 int *cur_index
, Sym
**cur_field
,
3406 int notfirst
, index
, align
, l
;
3409 if (gnu_ext
&& (l
= is_label()) != 0)
3412 while (tok
== '[' || tok
== '.') {
3414 if (!(t
& VT_ARRAY
))
3415 expect("array type");
3416 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3418 index
= expr_const();
3419 if (index
< 0 || (s
->c
>= 0 && index
>= s
->c
))
3420 expect("invalid index");
3424 t
= pointed_type(t
);
3425 c
+= index
* type_size(t
, &align
);
3431 if ((t
& VT_BTYPE
) != VT_STRUCT
)
3432 expect("struct/union type");
3433 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
3445 t
= f
->t
| (t
& ~VT_TYPE
);
3460 t
= pointed_type(t
);
3461 c
+= index
* type_size(t
, &align
);
3465 error("too many field init");
3466 t
= f
->t
| (t
& ~VT_TYPE
);
3470 decl_initializer(t
, c
, 0, size_only
);
3473 /* store a value or an expression directly in global data or in local array */
3475 void init_putv(int t
, int c
, int v
, int is_expr
)
3477 int saved_global_expr
;
3479 if ((t
& VT_VALMASK
) == VT_CONST
) {
3481 /* compound literals must be allocated globally in this case */
3482 saved_global_expr
= global_expr
;
3485 global_expr
= saved_global_expr
;
3487 if ((t
& VT_BTYPE
) == VT_BYTE
)
3489 else if ((t
& VT_BTYPE
) == VT_SHORT
)
3505 /* put zeros for variable based init */
3506 void init_putz(int t
, int c
, int size
)
3510 if ((t
& VT_VALMASK
) == VT_CONST
) {
3511 /* nothing to do because global are already set to zero */
3514 vset(VT_CONST
, size
);
3520 vset(VT_CONST
, (int)&memset
);
3525 /* 't' contains the type and storage info. c is the address of the
3526 object. 'first' is true if array '{' must be read (multi dimension
3527 implicit array init handling). 'size_only' is true if size only
3528 evaluation is wanted (only for arrays). */
3529 void decl_initializer(int t
, int c
, int first
, int size_only
)
3531 int index
, array_length
, n
, no_oblock
, nb
, parlevel
, i
;
3532 int t1
, size1
, align1
;
3537 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
));
3540 t1
= pointed_type(t
);
3541 size1
= type_size(t1
, &align1
);
3544 if ((first
&& tok
!= TOK_LSTR
&& tok
!= TOK_STR
) ||
3550 /* only parse strings here if correct type (otherwise: handle
3551 them as ((w)char *) expressions */
3552 if ((tok
== TOK_LSTR
&&
3553 (t1
& VT_BTYPE
) == VT_INT
) ||
3555 (t1
& VT_BTYPE
) == VT_BYTE
)) {
3556 /* XXX: move multiple string parsing in parser ? */
3557 while (tok
== TOK_STR
|| tok
== TOK_LSTR
) {
3558 ts
= (TokenSym
*)tokc
;
3559 /* compute maximum number of chars wanted */
3561 if (n
>= 0 && nb
> (n
- array_length
))
3562 nb
= n
- array_length
;
3565 warning("initializer-string for array is too long");
3567 init_putv(t1
, c
+ (array_length
+ i
) * size1
,
3574 /* only add trailing zero if enough storage (no
3575 warning in this case since it is standard) */
3576 if (n
< 0 || array_length
< n
) {
3578 init_putv(t1
, c
+ (array_length
* size1
), 0, 0);
3584 while (tok
!= '}') {
3585 decl_designator(t
, c
, &index
, NULL
, size_only
);
3586 if (n
>= 0 && index
>= n
)
3587 error("index too large");
3588 /* must put zero in holes (note that doing it that way
3589 ensures that it even works with designators) */
3590 if (!size_only
&& array_length
< index
) {
3591 init_putz(t1
, c
+ array_length
* size1
,
3592 (index
- array_length
) * size1
);
3595 if (index
> array_length
)
3596 array_length
= index
;
3597 /* special test for multi dimensional arrays (may not
3598 be strictly correct if designators are used at the
3600 if (index
>= n
&& no_oblock
)
3609 /* put zeros at the end */
3610 if (!size_only
&& n
>= 0 && array_length
< n
) {
3611 init_putz(t1
, c
+ array_length
* size1
,
3612 (n
- array_length
) * size1
);
3614 /* patch type size if needed */
3616 s
->c
= array_length
;
3617 } else if ((t
& VT_BTYPE
) == VT_STRUCT
&& tok
== '{') {
3618 /* XXX: union needs only one init */
3620 s
= sym_find(((unsigned)t
>> VT_STRUCT_SHIFT
) | SYM_STRUCT
);
3625 while (tok
!= '}') {
3626 decl_designator(t
, c
, NULL
, &f
, size_only
);
3627 /* fill with zero between fields */
3629 if (!size_only
&& array_length
< index
) {
3630 init_putz(t
, c
+ array_length
,
3631 index
- array_length
);
3633 index
= index
+ type_size(f
->t
, &align1
);
3634 if (index
> array_length
)
3635 array_length
= index
;
3641 /* put zeros at the end */
3642 if (!size_only
&& array_length
< n
) {
3643 init_putz(t
, c
+ array_length
,
3647 } else if (tok
== '{') {
3649 decl_initializer(t
, c
, first
, size_only
);
3651 } else if (size_only
) {
3652 /* just skip expression */
3654 while ((parlevel
> 0 || (tok
!= '}' && tok
!= ',')) &&
3658 else if (tok
== ')')
3663 init_putv(t
, c
, 0, 1);
3667 /* parse an initializer for type 't' if 'has_init' is true, and
3668 allocate space in local or global data space. The allocated address
3670 int decl_initializer_alloc(int t
, int has_init
)
3672 int size
, align
, addr
, tok1
;
3673 int *init_str
, init_len
, level
, *saved_macro_ptr
;
3675 size
= type_size(t
, &align
);
3676 /* If unknown size, we must evaluate it before
3677 evaluating initializers because
3678 initializers can generate global data too
3679 (e.g. string pointers or ISOC99 compound
3680 literals). It also simplifies local
3681 initializers handling */
3684 saved_macro_ptr
= NULL
; /* avoid warning */
3688 error("unknown type size");
3689 /* get all init string */
3691 while (level
> 0 || (tok
!= ',' && tok
!= ';')) {
3693 error("unexpect end of file in initializer");
3694 tok_add2(&init_str
, &init_len
, tok
, tokc
);
3697 else if (tok
== '}') {
3705 tok_add(&init_str
, &init_len
, -1);
3706 tok_add(&init_str
, &init_len
, 0);
3709 saved_macro_ptr
= macro_ptr
;
3710 macro_ptr
= init_str
;
3712 decl_initializer(t
, 0, 1, 1);
3713 /* prepare second initializer parsing */
3714 macro_ptr
= init_str
;
3717 /* if still unknown size, error */
3718 size
= type_size(t
, &align
);
3720 error("unknown type size");
3722 if ((t
& VT_VALMASK
) == VT_LOCAL
) {
3723 loc
= (loc
- size
) & -align
;
3726 glo
= (glo
+ align
- 1) & -align
;
3728 /* very important to increment global
3729 pointer at this time because
3730 initializers themselves can create new
3735 decl_initializer(t
, addr
, 1, 0);
3736 /* restore parse state if needed */
3739 macro_ptr
= saved_macro_ptr
;
3747 /* 'l' is VT_LOCAL or VT_CONST to define default storage type */
3750 int *a
, t
, b
, v
, u
, addr
, has_init
, size
, align
;
3756 /* skip redundant ';' */
3757 /* XXX: find more elegant solution */
3762 /* special test for old K&R protos without explicit int
3763 type. Only accepted when defining global data */
3764 if (l
== VT_LOCAL
|| tok
< TOK_DEFINE
)
3768 if (((b
& VT_BTYPE
) == VT_ENUM
||
3769 (b
& VT_BTYPE
) == VT_STRUCT
) &&
3771 /* we accept no variable after */
3775 while (1) { /* iterate thru each declaration */
3776 t
= type_decl(&v
, b
, TYPE_DIRECT
);
3779 error("cannot use local functions");
3781 expect("function definition");
3782 /* patch forward references */
3783 if ((sym
= sym_find(v
)) && (sym
->t
& VT_FORWARD
)) {
3784 greloc_patch(sym
, ind
);
3785 sym
->t
= VT_CONST
| t
;
3787 /* put function address */
3788 sym_push1(&global_stack
, v
, VT_CONST
| t
, ind
);
3790 funcname
= get_tok_str(v
, 0);
3791 /* push a dummy symbol to enable local sym storage */
3792 sym_push1(&local_stack
, 0, 0, 0);
3793 /* define parameters */
3794 sym
= sym_find((unsigned)t
>> VT_STRUCT_SHIFT
);
3795 /* XXX: the following is x86 dependant -> move it to
3798 /* if the function returns a structure, then add an
3799 implicit pointer parameter */
3801 if ((func_vt
& VT_BTYPE
) == VT_STRUCT
) {
3805 while (sym
= sym
->next
) {
3807 sym_push(sym
->v
& ~SYM_FIELD
,
3808 u
| VT_LOCAL
| VT_LVAL
,
3810 if ((u
& VT_BTYPE
) == VT_STRUCT
) {
3811 #ifdef FUNC_STRUCT_PARAM_AS_PTR
3812 /* structs are passed as pointer */
3815 /* structs are directly put on stack (x86
3817 size
= type_size(u
, &align
);
3818 size
= (size
+ 3) & ~3;
3821 /* XXX: size will be different someday */
3827 o(0xe58955); /* push %ebp, mov %esp, %ebp */
3828 a
= (int *)oad(0xec81, 0); /* sub $xxx, %esp */
3830 block(0, 0, 0, 0, 0);
3832 o(0xc3c9); /* leave, ret */
3833 *a
= (-loc
+ 3) & -4; /* align local size to word &
3834 save local variables */
3835 sym_pop(&label_stack
, 0); /* reset label stack */
3836 sym_pop(&local_stack
, 0); /* reset local stack */
3837 funcname
= ""; /* for safety */
3838 func_vt
= VT_VOID
; /* for safety */
3841 if (b
& VT_TYPEDEF
) {
3842 /* save typedefed type */
3843 /* XXX: test storage specifiers ? */
3844 sym_push(v
, t
| VT_TYPEDEF
, 0);
3845 } else if ((t
& VT_BTYPE
) == VT_FUNC
) {
3846 /* external function definition */
3849 /* not lvalue if array */
3850 if (!(t
& VT_ARRAY
))
3852 if (b
& VT_EXTERN
) {
3853 /* external variable */
3860 has_init
= (tok
== '=');
3863 addr
= decl_initializer_alloc(u
, has_init
);
3864 if (l
== VT_CONST
) {
3865 /* global scope: see if already defined */
3869 if (!is_compatible_types(sym
->t
, u
))
3870 error("incompatible types for redefinition of '%s'",
3872 if (!(sym
->t
& VT_FORWARD
))
3873 error("redefinition of '%s'", get_tok_str(v
, 0));
3874 greloc_patch(sym
, addr
);
3877 sym_push(v
, u
, addr
);
3891 /* put all global symbols in the extern stack and do all the
3892 resolving which can be done without using external symbols from DLLs */
3893 /* XXX: could try to verify types, but would not to save them in
3895 void resolve_global_syms(void)
3897 Sym
*s
, *s1
, *ext_sym
;
3900 s
= global_stack
.top
;
3903 /* do not save static or typedefed symbols or types */
3904 if (!(s
->t
& (VT_STATIC
| VT_TYPEDEF
)) &&
3905 !(s
->v
& (SYM_FIELD
| SYM_STRUCT
)) &&
3906 (s
->v
< SYM_FIRST_ANOM
)) {
3907 ext_sym
= sym_find1(&extern_stack
, s
->v
);
3909 /* if the symbol do not exist, we simply save it */
3910 sym_push1(&extern_stack
, s
->v
, s
->t
, s
->c
);
3911 } else if (ext_sym
->t
& VT_FORWARD
) {
3912 /* external symbol already exists, but only as forward
3914 if (!(s
->t
& VT_FORWARD
)) {
3915 /* s is not forward, so we can relocate all symbols */
3916 greloc_patch(ext_sym
, s
->c
);
3918 /* the two symbols are forward: merge them */
3919 p
= (Reloc
**)&ext_sym
->c
;
3925 /* external symbol already exists and is defined :
3926 patch all references to it */
3927 if (!(s
->t
& VT_FORWARD
))
3928 error("'%s' defined twice", get_tok_str(s
->v
, 0));
3929 greloc_patch(s
, ext_sym
->c
);
3936 /* compile a C file. Return non zero if errors. */
3937 int tcc_compile_file(const char *filename1
)
3941 filename
= (char *)filename1
;
3945 file
= fopen(filename
, "r");
3947 error("file '%s' not found", filename
);
3948 include_stack_ptr
= include_stack
;
3949 ifdef_stack_ptr
= ifdef_stack
;
3951 vstack_ptr
= vstack
;
3952 anon_sym
= SYM_FIRST_ANOM
;
3954 define_start
= define_stack
.top
;
3956 ch
= '\n'; /* needed to parse correctly first preprocessor command */
3960 expect("declaration");
3963 /* reset define stack, but leave -Dsymbols (may be incorrect if
3964 they are undefined) */
3965 sym_pop(&define_stack
, define_start
);
3967 resolve_global_syms();
3969 sym_pop(&global_stack
, NULL
);
3974 /* open a dynamic library so that its symbol are available for
3975 compiled programs */
3976 void open_dll(char *libname
)
3981 snprintf(buf
, sizeof(buf
), "lib%s.so", libname
);
3982 h
= dlopen(buf
, RTLD_GLOBAL
| RTLD_LAZY
);
3984 error((char *)dlerror());
3987 void resolve_extern_syms(void)
3993 s
= extern_stack
.top
;
3996 if (s
->t
& VT_FORWARD
) {
3997 /* if there is at least one relocation to do, then find it
4000 str
= get_tok_str(s
->v
, 0);
4001 addr
= (int)dlsym(NULL
, str
);
4003 error("unresolved external reference '%s'", str
);
4004 greloc_patch(s
, addr
);
4011 /* output a binary file (for testing) */
4012 void build_exe(char *filename
)
4015 f
= fopen(filename
, "w");
4016 fwrite((void *)prog
, 1, ind
- prog
, f
);
4020 int main(int argc
, char **argv
)
4024 char *p
, *r
, *outfile
;
4027 include_paths
[0] = "/usr/include";
4028 include_paths
[1] = "/usr/lib/tcc";
4029 include_paths
[2] = "/usr/local/lib/tcc";
4030 nb_include_paths
= 3;
4032 /* add all tokens */
4033 tok_ident
= TOK_IDENT
;
4034 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";
4038 tok_alloc(p
, r
- p
- 1);
4042 /* standard defines */
4043 define_symbol("__STDC__");
4045 define_symbol("__i386__");
4047 /* tiny C specific defines */
4048 define_symbol("__TINYC__");
4050 glo
= (int)malloc(DATA_SIZE
);
4051 memset((void *)glo
, 0, DATA_SIZE
);
4052 prog
= (int)malloc(TEXT_SIZE
);
4058 if (optind
>= argc
) {
4060 printf("tcc version 0.9.1 - Tiny C Compiler - Copyright (C) 2001 Fabrice Bellard\n"
4061 "usage: tcc [-Idir] [-Dsym] [-llib] [-i infile]... infile [infile_args...]\n");
4069 if (nb_include_paths
>= INCLUDE_PATHS_MAX
)
4070 error("too many include paths");
4071 include_paths
[nb_include_paths
++] = r
+ 2;
4072 } else if (r
[1] == 'D') {
4073 define_symbol(r
+ 2);
4074 } else if (r
[1] == 'l') {
4076 } else if (r
[1] == 'i') {
4079 tcc_compile_file(argv
[optind
++]);
4080 } else if (r
[1] == 'o') {
4081 /* currently, only for testing, so not documented */
4084 outfile
= argv
[optind
++];
4086 fprintf(stderr
, "invalid option -- '%s'\n", r
);
4091 tcc_compile_file(argv
[optind
]);
4093 resolve_extern_syms();
4099 s
= sym_find1(&extern_stack
, TOK_MAIN
);
4100 if (!s
|| (s
->t
& VT_FORWARD
))
4101 error("main() not defined");
4102 t
= (int (*)())s
->c
;
4103 return (*t
)(argc
- optind
, argv
+ optind
);