-
Notifications
You must be signed in to change notification settings - Fork 0
/
zcc.h
265 lines (239 loc) · 6.83 KB
/
zcc.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
/* zcc.h */
#include <stdio.h>
struct list_st;
struct type_st;
struct context_st;
struct func_st;
struct var_st;
union value_un;
struct token_st;
enum ir_op_en;
/* structs */
typedef struct type_st {
int bytes;
int native; /* is native type */
struct type_st* ref; /* ref != NULL if its pointer */
char *name; /* name == NULL for pointer */
} type_st;
typedef struct func_st {
char *name;
struct type_st *rtype;
struct list_st *pars; /* list of var_st */
struct list_st *insts;
struct var_st *ret;
int declared;
int defined;
/* for gen */
int rbytes; /* bytes should reserved for local variables */
} func_st;
typedef struct list_st {
void **elems;
int len;
int room; /* reservered size */
} list_st;
typedef struct var_st {
char *name;
struct type_st *type;
union value_un *value;
int ispar; /* 0 if not parameter. otherwise parameter index. (i.e. ispar=1 for the first parameter) */
int lvalue;
/* for ir & gen */
char *irname;
#define STACK_VAR 0
#define HEAP_VAR 1
int where;
/* ref == 1 indicates this var is a lvalue and is indirectly access.
* i.e. the address of var but not var itself is store on stack or heap
*/
int ref;
/* var address for stack_var.
* access by -(addr+8)(%rbp)
* heap_var is access by name(%rip)
*/
int addr;
} var_st;
typedef struct scope_st {
struct scope_st *up;
struct list_st *vars; /* list of var_st* */
struct label_st *forC; /* condition */
struct label_st *forB; /* body */
struct label_st *forE;
} scope_st;
typedef struct label_st {
struct func_st *func;
struct label_st *chain; /* shared label. */
char *irname;
} label_st;
typedef struct context_st {
struct scope_st *scope;
struct func_st *func;
struct list_st *funcs; /* list of func_st* */
struct list_st *types; /* list of type_st*. in C, types are global */
struct list_st *cstr; /* list of var_st*, const string */
} context_st;
typedef enum ir_op_en {
IR_ADD = 0, /* (var, var, var) */
IR_SUB, /* ... */
IR_MUL, /* ... */
IR_DIV, /* ... */
IR_RETURN, /* (var) */
IR_CALL, /* (var, func, list<var>) */
IR_ASSIGN, /* (var, var) */
IR_LABEL, /* (label) */
IR_JMP, /* (label) */
IR_CJMP, /* (var, label) */
IR_LT, /* (var, var, var) */
IR_LE, /* ... */
IR_EQ, /* ... */
IR_GT, /* ... */
IR_GE, /* ... */
IR_NEQ, /* ... */
IR_INC, /* (var) */
IR_DEC, /* ... */
IR_IND, /* (var, var, var) */
IR_OFFSET, /* (var, var, int) */
} ir_op_en;
typedef struct inst_st {
ir_op_en op;
void* args[3]; /* maximum 3 args */
} inst_st;
/* -- structs used for lexer -- */
enum lex_ecode_en {
ELEX_FILE_NULL = 1,
ELEX_FEOF
};
typedef enum tk_class_en {
TK_NO_CLASS = 0,
// keywords
#define xx(tk_class, u) tk_class,
#include "keywords.h"
#undef xx
// constant
TK_CONST_INT,
TK_CONST_CHAR,
TK_CONST_STRING,
// operator / delimiter
TK_OP,
#define xx(tk_class, u, v, w) tk_class,
#define yy(tk_class, u, v, w) tk_class,
#define zz(tk_class, u)
#include "operators.h"
#undef xx
#undef yy
#undef zz
TK_DELIMITER,
// others
TK_IDENTIFIER
} tk_class_en;
typedef union value_un {
int i;
char c;
char *s;
} value_un;
typedef struct token_st {
enum tk_class_en tk_class;
char *tk_str;
value_un *value;
} token_st;
/* public variables */
extern token_st lex_token;
extern context_st context;
extern type_st *type_int;
extern type_st *type_int_ptr;
extern type_st *type_char;
extern type_st *type_char_ptr;
extern func_st *wrap_func;
/* =-- forward declaration --= */
/* == lex == */
int lex_load_file(const char *);
void lex_print_token(token_st *);
void lex_init();
int lex_next();
int lex_getc();
int lex_isbinaryop(token_st*);
int lex_isunaryop(token_st*);
int lex_isassignop(token_st*);
int lex_valid();
/* == parse == */
void prs_init();
int prs_expect_char(char);
int prs_expect_class(tk_class_en);
/* -- expr -- */
var_st* prs_binary();
var_st* prs_expr();
var_st* prs_primary();
list_st* prs_args();
var_st* prs_unary();
var_st* prs_pst(var_st*);
var_st* prs_assign();
var_st* prs_cond();
/* -- stmt -- */
int prs_stmt_return();
int prs_stmt_if();
int prs_stmt_else();
int prs_stmt_for();
int prs_stmt_while();
int prs_stmt_dowhile();
int prs_stmt_switch();
int prs_stmt_break();
int prs_stmt_continue();
int prs_stmt();
/* -- decl -- */
int prs_decls();
int prs_decl();
type_st* prs_decl_spec();
/* == sym == */
int sym_init();
int sym_hasid(token_st*);
int sym_hastype(token_st*);
int sym_islabel(token_st*);
int sym_is_pointer(var_st*);
scope_st* sym_make_scope();
scope_st* sym_mnp_scope(); /* make and push scope to context */
void sym_push_scope(scope_st*);
void sym_pop_scope();
int sym_redefined_var(char*);
var_st* sym_make_var(char*, type_st*);
var_st* sym_find_var(char*);
var_st* sym_add_var(var_st*);
var_st* sym_make_temp_var(type_st*);
var_st* sym_make_temp_lvar(type_st*, int);
void sym_dispose_temp_var(var_st*);
var_st* sym_make_imm(token_st*);
var_st* sym_make_par(char*, type_st*);
func_st* sym_make_func(char*, type_st*);
int sym_is_full_pars(func_st*);
func_st* sym_make_temp_func(char*, type_st*);
func_st* sym_find_func(char*);
void sym_add_type(type_st*);
label_st* sym_make_label();
var_st* sym_deref(var_st*);
type_st* pointer_of(type_st*);
type_st* binop_res_type(ir_op_en, type_st*, type_st*);
/* == gen == */
void gen_emit0(ir_op_en);
void gen_emit1(ir_op_en, void*);
void gen_emit2(ir_op_en, void*, void*);
void gen_emit3(ir_op_en, void*, void*, void*);
void gen_emit_call(ir_op_en, func_st*, var_st*, list_st*);
void gen_emit_offset(var_st*, var_st*, int);
void gen_print_func_ir(func_st*);
/* target-specific gen
* link gen-x.c to support different target
*/
void gen_assembly(FILE*);
/* util */
void fexit(const char *format, ...);
char* dup_str(char*);
var_st* dup_arg(ir_op_en, int, var_st*);
var_st* dup_temp_var(var_st*);
value_un* dup_value(token_st*);
list_st* make_list();
void* list_append(list_st*, void*);
void* list_pop(list_st*);
int list_isempty(list_st*);
int list_index(list_st*, void*);
/*==-- Macros --==*/
#define EMIT_M_MACRO(_0,_1,_2, _3, NAME, ...) NAME
#define gen_emit(...) EMIT_M_MACRO(__VA_ARGS__, gen_emit3, gen_emit2, gen_emit1, gen_emit0)(__VA_ARGS__)
#define DEMINER fprintf(stderr, "Run upon Line %d\n", __LINE__);