diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/generator.c | 146 | ||||
-rw-r--r-- | src/generator.h | 5 | ||||
-rw-r--r-- | src/symbol_table.c | 10 | ||||
-rw-r--r-- | src/symbol_table.h | 6 | ||||
-rw-r--r-- | src/tpc.y | 23 |
5 files changed, 142 insertions, 48 deletions
diff --git a/src/generator.c b/src/generator.c index ab3777c..5c51d3b 100644 --- a/src/generator.c +++ b/src/generator.c | |||
@@ -13,7 +13,8 @@ void gen_prologue() { | |||
13 | } | 13 | } |
14 | 14 | ||
15 | void gen_prologue_continue(int *bss_done) { | 15 | void gen_prologue_continue(int *bss_done) { |
16 | if (*bss_done != 0) return; | 16 | if (*bss_done != 0) |
17 | return; | ||
17 | 18 | ||
18 | fprintf(output, "format_int db \"%%d\",10,0\n"); | 19 | fprintf(output, "format_int db \"%%d\",10,0\n"); |
19 | fprintf(output, "format_char db \"%%c\",10,0\n"); | 20 | fprintf(output, "format_char db \"%%c\",10,0\n"); |
@@ -112,9 +113,10 @@ Type gen_function_declaration(const char name[], int return_type) { | |||
112 | return return_type; | 113 | return return_type; |
113 | } | 114 | } |
114 | 115 | ||
115 | void gen_function_end_declaration(const char name[], int return_type, int nb_param) { | 116 | void gen_function_end_declaration(const char name[], int return_type, |
117 | int nb_param) { | ||
116 | fun_add(name, return_type, nb_param); | 118 | fun_add(name, return_type, nb_param); |
117 | fprintf(output, "mov rax,-1\nmov rsp, rbp\npop rbp\nret\n"); | 119 | fprintf(output, "mov rax,-1\nmov rsp, rbp\npop rbp\nret\n"); |
118 | } | 120 | } |
119 | 121 | ||
120 | void gen_function_return(Type expect, Type actual) { | 122 | void gen_function_return(Type expect, Type actual) { |
@@ -122,14 +124,16 @@ void gen_function_return(Type expect, Type actual) { | |||
122 | fprintf(stderr, "Return type mismatch at line %d.", lineno); | 124 | fprintf(stderr, "Return type mismatch at line %d.", lineno); |
123 | exit(1); | 125 | exit(1); |
124 | } | 126 | } |
125 | if (actual != VOID_T) fprintf(output, "pop rax\n"); | 127 | if (actual != VOID_T) |
128 | fprintf(output, "pop rax\n"); | ||
126 | fprintf(output, "mov rsp, rbp\npop rbp\nret\n"); | 129 | fprintf(output, "mov rsp, rbp\npop rbp\nret\n"); |
127 | } | 130 | } |
128 | 131 | ||
129 | Type gen_function_call(const char name[], int nb_param) { | 132 | Type gen_function_call(const char name[], int nb_param) { |
130 | Type return_type = fun_lookup(name, nb_param); | 133 | Type return_type = fun_lookup(name, nb_param); |
131 | fprintf(output, "call %s\n", name); | 134 | fprintf(output, "call %s\n", name); |
132 | if (return_type != VOID_T) fprintf(output, "push rax\n"); | 135 | if (return_type != VOID_T) |
136 | fprintf(output, "push rax\n"); | ||
133 | return return_type; | 137 | return return_type; |
134 | } | 138 | } |
135 | 139 | ||
@@ -146,6 +150,21 @@ void gen_declaration(const char name[], int type, Scope scope) { | |||
146 | } | 150 | } |
147 | } | 151 | } |
148 | 152 | ||
153 | void gen_tab_declaration(const char name[], Scope scope, int size) { | ||
154 | switch (scope) { | ||
155 | case GLOBAL: | ||
156 | glo_addVar(name, TAB); | ||
157 | nb_globals = nb_globals + size; | ||
158 | break; | ||
159 | case LOCAL: | ||
160 | loc_addVar(name, TAB); | ||
161 | for (int i = 0; i < size; ++i) { | ||
162 | fprintf(output, "push 0\n"); | ||
163 | } | ||
164 | break; | ||
165 | } | ||
166 | } | ||
167 | |||
149 | // Verifies that the variable exists | 168 | // Verifies that the variable exists |
150 | void gen_check(const char name[], Scope scope) { | 169 | void gen_check(const char name[], Scope scope) { |
151 | switch (scope) { | 170 | switch (scope) { |
@@ -161,8 +180,8 @@ void gen_check(const char name[], Scope scope) { | |||
161 | // ----- READ AND PRINT FUNCTIONS ----- | 180 | // ----- READ AND PRINT FUNCTIONS ----- |
162 | void gen_reade(const char name[], Scope scope) { | 181 | void gen_reade(const char name[], Scope scope) { |
163 | if (is_read_only(name, scope)) { | 182 | if (is_read_only(name, scope)) { |
164 | fprintf(stderr, "Symbol \"%s\" at line %d is read only.\n", name, lineno); | 183 | fprintf(stderr, "Symbol \"%s\" at line %d is read only.\n", name, lineno); |
165 | exit(1); | 184 | exit(1); |
166 | } | 185 | } |
167 | 186 | ||
168 | if (loc_lookup(name) != INT) { | 187 | if (loc_lookup(name) != INT) { |
@@ -181,8 +200,8 @@ void gen_reade(const char name[], Scope scope) { | |||
181 | 200 | ||
182 | void gen_readc(const char name[], Scope scope) { | 201 | void gen_readc(const char name[], Scope scope) { |
183 | if (is_read_only(name, scope)) { | 202 | if (is_read_only(name, scope)) { |
184 | fprintf(stderr, "Symbol \"%s\" at line %d is read only.\n", name, lineno); | 203 | fprintf(stderr, "Symbol \"%s\" at line %d is read only.\n", name, lineno); |
185 | exit(1); | 204 | exit(1); |
186 | } | 205 | } |
187 | 206 | ||
188 | if (loc_lookup(name) != CHAR) { | 207 | if (loc_lookup(name) != CHAR) { |
@@ -200,18 +219,21 @@ void gen_readc(const char name[], Scope scope) { | |||
200 | } | 219 | } |
201 | 220 | ||
202 | void gen_print(int type) { | 221 | void gen_print(int type) { |
203 | //check if the name exists in both tables | 222 | // check if the name exists in both tables |
204 | fprintf(output, "pop rax\n"); | 223 | fprintf(output, "pop rax\n"); |
205 | switch(type){ | 224 | switch (type) { |
206 | case INT: | 225 | case INT: |
207 | fprintf(output, "call printe\n"); | 226 | fprintf(output, "call printe\n"); |
227 | break; | ||
228 | case CHAR: | ||
229 | fprintf(output, "call printc\n"); | ||
208 | break; | 230 | break; |
209 | case CHAR: | 231 | case TAB: |
210 | fprintf(output, "call printc\n"); | 232 | fprintf(output, "call printe\n"); |
211 | break; | 233 | break; |
212 | default: fprintf(stderr, "Error print, supposed to have type CHAR or INT\n"); | 234 | default: |
235 | fprintf(stderr, "Error print, supposed to have type CHAR or INT or TAB\n"); | ||
213 | } | 236 | } |
214 | |||
215 | } | 237 | } |
216 | 238 | ||
217 | // ----- CONDITIONAL BRANCHING ------ | 239 | // ----- CONDITIONAL BRANCHING ------ |
@@ -245,14 +267,13 @@ int gen_assign(const char ident[], Scope scope) { | |||
245 | int g_addr = glo_get_addr(ident); | 267 | int g_addr = glo_get_addr(ident); |
246 | 268 | ||
247 | if (is_read_only(ident, scope)) { | 269 | if (is_read_only(ident, scope)) { |
248 | fprintf(stderr, "Symbol \"%s\" at line %d is read only.\n", ident, lineno); | 270 | fprintf(stderr, "Symbol \"%s\" at line %d is read only.\n", ident, lineno); |
249 | exit(1); | 271 | exit(1); |
250 | } | 272 | } |
251 | 273 | ||
252 | switch (scope) { | 274 | switch (scope) { |
253 | case GLOBAL: | 275 | case GLOBAL: |
254 | fprintf(output, "pop QWORD [globals + %d] ;%s\n", g_addr, | 276 | fprintf(output, "pop QWORD [globals + %d] ;%s\n", g_addr, ident); |
255 | ident); | ||
256 | return glo_lookup(ident); | 277 | return glo_lookup(ident); |
257 | case LOCAL: | 278 | case LOCAL: |
258 | if (l_addr != -1) { | 279 | if (l_addr != -1) { |
@@ -267,9 +288,35 @@ int gen_assign(const char ident[], Scope scope) { | |||
267 | } | 288 | } |
268 | } | 289 | } |
269 | 290 | ||
291 | int gen_assign_tab(const char ident[], Scope scope) { | ||
292 | int l_addr = loc_get_addr(ident); | ||
293 | int g_addr = glo_get_addr(ident); | ||
294 | |||
295 | if (is_read_only(ident, scope)) { | ||
296 | fprintf(stderr, "Symbol \"%s\" at line %d is read only.\n", ident, lineno); | ||
297 | exit(1); | ||
298 | } | ||
299 | |||
300 | switch (scope) { | ||
301 | case GLOBAL: | ||
302 | fprintf(output, "pop r8 ;EXP\npop rcx ;offset\npush r8\nimul rcx,8\nmov rax,globals\n add rax,rcx\npop QWORD [rax + %d] ;%s\n", g_addr, ident); | ||
303 | return glo_lookup(ident); | ||
304 | case LOCAL: | ||
305 | if (l_addr != -1) { | ||
306 | fprintf(output, "pop r8 ;EXP\npop rcx ;offset\npush r8\nimul rcx,8\nmov rax,rbp\nsub rax,rcx\npop QWORD [rax - %d] ;%s\n", l_addr, ident); | ||
307 | return loc_lookup(ident); | ||
308 | } else { | ||
309 | fprintf(output, "pop r8 ;EXP\npop rcx ;offset\npush r8\nimul rcx,8\nmov rax,globals\n add rax,rcx\npop QWORD [rax + %d] ;%s\n", g_addr, ident); | ||
310 | return glo_lookup(ident); | ||
311 | } | ||
312 | default: | ||
313 | exit(1); | ||
314 | } | ||
315 | } | ||
316 | |||
270 | void gen_or(int left, int right, int idx) { | 317 | void gen_or(int left, int right, int idx) { |
271 | check_expected_type(left, INT); | 318 | check_expected_types(left, INT,TAB); |
272 | check_expected_type(right, INT); | 319 | check_expected_types(right, INT,TAB); |
273 | 320 | ||
274 | fprintf(output, ";a OR c\n"); | 321 | fprintf(output, ";a OR c\n"); |
275 | fprintf(output, "pop rax\n"); | 322 | fprintf(output, "pop rax\n"); |
@@ -286,8 +333,8 @@ void gen_or(int left, int right, int idx) { | |||
286 | } | 333 | } |
287 | 334 | ||
288 | void gen_and(int left, int right, int idx) { | 335 | void gen_and(int left, int right, int idx) { |
289 | check_expected_type(left, INT); | 336 | check_expected_types(left, INT,TAB); |
290 | check_expected_type(right, INT); | 337 | check_expected_types(right, INT,TAB); |
291 | 338 | ||
292 | fprintf(output, ";a AND c\n"); | 339 | fprintf(output, ";a AND c\n"); |
293 | fprintf(output, "pop rax\n"); | 340 | fprintf(output, "pop rax\n"); |
@@ -304,8 +351,8 @@ void gen_and(int left, int right, int idx) { | |||
304 | } | 351 | } |
305 | 352 | ||
306 | void gen_eq(const char op[], int left, int right, int idx) { | 353 | void gen_eq(const char op[], int left, int right, int idx) { |
307 | check_expected_type(left, INT); | 354 | check_expected_types(left, INT,TAB); |
308 | check_expected_type(right, INT); | 355 | check_expected_types(right, INT,TAB); |
309 | 356 | ||
310 | fprintf(output, ";a EQ c\npop rax\npop rcx\ncmp rax,rcx\n"); | 357 | fprintf(output, ";a EQ c\npop rax\npop rcx\ncmp rax,rcx\n"); |
311 | 358 | ||
@@ -316,13 +363,13 @@ void gen_eq(const char op[], int left, int right, int idx) { | |||
316 | else | 363 | else |
317 | exit(1); // TODO: error on unexpected op | 364 | exit(1); // TODO: error on unexpected op |
318 | 365 | ||
319 | fprintf(output, "push 0\njmp .false%d\n.true%d:\npush 1\n.false%d:\n", idx, idx, | 366 | fprintf(output, "push 0\njmp .false%d\n.true%d:\npush 1\n.false%d:\n", idx, |
320 | idx); | 367 | idx, idx); |
321 | } | 368 | } |
322 | 369 | ||
323 | void gen_order(const char op[], int left, int right, int idx) { | 370 | void gen_order(const char op[], int left, int right, int idx) { |
324 | check_expected_type(left, INT); | 371 | check_expected_types(left, INT,TAB); |
325 | check_expected_type(right, INT); | 372 | check_expected_types(right, INT,TAB); |
326 | 373 | ||
327 | fprintf(output, ";a ORDER c\npop rcx\npop rax\ncmp rax,rcx\n"); | 374 | fprintf(output, ";a ORDER c\npop rcx\npop rax\ncmp rax,rcx\n"); |
328 | 375 | ||
@@ -337,13 +384,13 @@ void gen_order(const char op[], int left, int right, int idx) { | |||
337 | else | 384 | else |
338 | exit(1); // TODO: error on unexpected op | 385 | exit(1); // TODO: error on unexpected op |
339 | 386 | ||
340 | fprintf(output, "push 0\njmp .false%d\n.true%d:\npush 1\n.false%d:\n", idx, idx, | 387 | fprintf(output, "push 0\njmp .false%d\n.true%d:\npush 1\n.false%d:\n", idx, |
341 | idx); | 388 | idx, idx); |
342 |