diff options
-rw-r--r-- | doc/rapport.md | 7 | ||||
-rw-r--r-- | src/generator.c | 81 | ||||
-rw-r--r-- | src/symbol_table.c | 42 |
3 files changed, 72 insertions, 58 deletions
diff --git a/doc/rapport.md b/doc/rapport.md index d1c0226..28f8446 100644 --- a/doc/rapport.md +++ b/doc/rapport.md | |||
@@ -96,6 +96,13 @@ Dans les langages tel que le C, l'associativité se fait à gauche. | |||
96 | On déclare donc `%left ,` pour l'indiquer à Bison. | 96 | On déclare donc `%left ,` pour l'indiquer à Bison. |
97 | 97 | ||
98 | 98 | ||
99 | # Analyse sémantique | ||
100 | |||
101 | Le compilateur gère l'analyse sémantique. | ||
102 | Par exemple l'opération `tab[1] * 3` est légale mais `'a' * 'b'` ne l'est pas. La grammaire l'accepte, mais l'analyse sémantique à parti des attributs interdits. | ||
103 | |||
104 | |||
105 | |||
99 | # Génération de code cible | 106 | # Génération de code cible |
100 | 107 | ||
101 | ## Gestion de la mémoire | 108 | ## Gestion de la mémoire |
diff --git a/src/generator.c b/src/generator.c index b75f7a8..1b11b67 100644 --- a/src/generator.c +++ b/src/generator.c | |||
@@ -4,7 +4,7 @@ | |||
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include "generator.h" | 6 | #include "generator.h" |
7 | 7 | void yyerror(char *); | |
8 | // ----- GLOBAL FUNCTIONS ----- | 8 | // ----- GLOBAL FUNCTIONS ----- |
9 | 9 | ||
10 | void gen_prologue() { | 10 | void gen_prologue() { |
@@ -21,7 +21,6 @@ void gen_prologue_continue(int *bss_done) { | |||
21 | fprintf(output, "format_int_in: db \"%%d\", 0\n"); | 21 | fprintf(output, "format_int_in: db \"%%d\", 0\n"); |
22 | fprintf(output, "format_char_in: db \"%%c\", 0\n\n"); | 22 | fprintf(output, "format_char_in: db \"%%c\", 0\n\n"); |
23 | fprintf(output, "section .bss\n"); | 23 | fprintf(output, "section .bss\n"); |
24 | |||
25 | fprintf(output, "globals: resq %d\n", nb_globals); | 24 | fprintf(output, "globals: resq %d\n", nb_globals); |
26 | fprintf(output, "section .text\n\nglobal _start\n"); | 25 | fprintf(output, "section .text\n\nglobal _start\n"); |
27 | fprintf(output, "\nprinte: ;print needs an argument in rax\n"); | 26 | fprintf(output, "\nprinte: ;print needs an argument in rax\n"); |
@@ -124,8 +123,8 @@ void gen_function_end_declaration(const char name[], int return_type, | |||
124 | 123 | ||
125 | void gen_function_return(Type expect, Type actual) { | 124 | void gen_function_return(Type expect, Type actual) { |
126 | if (actual != expect) { | 125 | if (actual != expect) { |
127 | fprintf(stderr, "Return type mismatch at line %d.\n", lineno); | 126 | yyerror("Return type mismatch"); |
128 | exit(1); | 127 | return; |
129 | } | 128 | } |
130 | if (actual != VOID_T) | 129 | if (actual != VOID_T) |
131 | fprintf(output, "pop rax\n"); | 130 | fprintf(output, "pop rax\n"); |
@@ -183,12 +182,12 @@ void gen_check(const char name[], Scope scope) { | |||
183 | // ----- READ AND PRINT FUNCTIONS ----- | 182 | // ----- READ AND PRINT FUNCTIONS ----- |
184 | void gen_reade(const char name[], Scope scope) { | 183 | void gen_reade(const char name[], Scope scope) { |
185 | if (is_read_only(name, scope)) { | 184 | if (is_read_only(name, scope)) { |
186 | fprintf(stderr, "Symbol \"%s\" at line %d is read only.\n", name, lineno); | 185 | yyerror("Symbol is read only"); |
187 | exit(1); | 186 | return; |
188 | } | 187 | } |
189 | 188 | ||
190 | if (loc_lookup(name) != INT) { | 189 | if (loc_lookup(name) != INT) { |
191 | fprintf(stderr, "Need to be a INT in the reade() function\n"); | 190 | yyerror("Need to be a INT in the reade() function"); |
192 | return; | 191 | return; |
193 | } | 192 | } |
194 | int l_addr = loc_get_addr(name); | 193 | int l_addr = loc_get_addr(name); |
@@ -203,12 +202,12 @@ void gen_reade(const char name[], Scope scope) { | |||
203 | 202 | ||
204 | void gen_readc(const char name[], Scope scope) { | 203 | void gen_readc(const char name[], Scope scope) { |
205 | if (is_read_only(name, scope)) { | 204 | if (is_read_only(name, scope)) { |
206 | fprintf(stderr, "Symbol \"%s\" at line %d is read only.\n", name, lineno); | 205 | yyerror("Symbol is read only"); |
207 | exit(1); | 206 | return; |
208 | } | 207 | } |
209 | 208 | ||
210 | if (loc_lookup(name) != CHAR) { | 209 | if (loc_lookup(name) != CHAR) { |
211 | fprintf(stderr, "Need to be a CHAR in the readc() function\n"); | 210 | yyerror("Need to be a CHAR in the readc() function"); |
212 | return; | 211 | return; |
213 | } | 212 | } |
214 | int l_addr = loc_get_addr(name); | 213 | int l_addr = loc_get_addr(name); |
@@ -235,7 +234,7 @@ void gen_print(int type) { | |||
235 | fprintf(output, "call printe\n"); | 234 | fprintf(output, "call printe\n"); |
236 | break; | 235 | break; |
237 | default: | 236 | default: |
238 | fprintf(stderr, "Error print, supposed to have type CHAR or INT or TAB\n"); | 237 | yyerror("Error print, supposed to have type CHAR or INT or TAB"); |
239 | } | 238 | } |
240 | } | 239 | } |
241 | 240 | ||
@@ -270,8 +269,8 @@ static int gen_assign_simple(const char ident[], Scope scope) { | |||
270 | int g_addr = glo_get_addr(ident); | 269 | int g_addr = glo_get_addr(ident); |
271 | 270 | ||
272 | if (is_read_only(ident, scope)) { | 271 | if (is_read_only(ident, scope)) { |
273 | fprintf(stderr, "Symbol \"%s\" at line %d is read only.\n", ident, lineno); | 272 | yyerror("Symbol is read only"); |
274 | exit(1); | 273 | return loc_lookup(ident); |
275 | } | 274 | } |
276 | 275 | ||
277 | switch (scope) { | 276 | switch (scope) { |
@@ -296,20 +295,26 @@ static int gen_assign_tab(const char ident[], Scope scope) { | |||
296 | int g_addr = glo_get_addr(ident); | 295 | int g_addr = glo_get_addr(ident); |
297 | 296 | ||
298 | if (is_read_only(ident, scope)) { | 297 | if (is_read_only(ident, scope)) { |
299 | fprintf(stderr, "Symbol \"%s\" at line %d is read only.\n", ident, lineno); | 298 | yyerror("Symbol is read only"); |
300 | exit(1); | 299 | return loc_lookup(ident); |
301 | } | 300 | } |
302 | 301 | ||
303 | switch (scope) { | 302 | switch (scope) { |
304 | case GLOBAL: | 303 | case GLOBAL: |
305 | 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); | 304 | fprintf(output, "pop r8 ;EXP\npop rcx ;offset\npush r8\nimul rcx,8\nmov " |
305 | "rax,globals\n add rax,rcx\npop QWORD [rax + %d] ;%s\n", | ||
306 | g_addr, ident); | ||
306 | return glo_lookup(ident); | 307 | return glo_lookup(ident); |
307 | case LOCAL: | 308 | case LOCAL: |
308 | if (l_addr != -1) { | 309 | if (l_addr != -1) { |
309 | 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); | 310 | fprintf(output, "pop r8 ;EXP\npop rcx ;offset\npush r8\nimul rcx,8\nmov " |
311 | "rax,rbp\nsub rax,rcx\npop QWORD [rax - %d] ;%s\n", | ||
312 | l_addr, ident); | ||
310 | return loc_lookup(ident); | 313 | return loc_lookup(ident); |
311 | } else { | 314 | } else { |
312 | 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); | 315 | fprintf(output, "pop r8 ;EXP\npop rcx ;offset\npush r8\nimul rcx,8\nmov " |
316 | "rax,globals\n add rax,rcx\npop QWORD [rax + %d] ;%s\n", | ||
317 | g_addr, ident); | ||
313 | return glo_lookup(ident); | 318 | return glo_lookup(ident); |
314 | } | 319 | } |
315 | default: | 320 | default: |
@@ -325,8 +330,8 @@ int gen_assign(const char ident[], Scope scope) { | |||
325 | } | 330 | } |
326 | 331 | ||
327 | void gen_or(int left, int right, int idx) { | 332 | void gen_or(int left, int right, int idx) { |
328 | check_expected_types(left, INT,TAB); | 333 | check_expected_types(left, INT, TAB); |
329 | check_expected_types(right, INT,TAB); | 334 | check_expected_types(right, INT, TAB); |
330 | 335 | ||
331 | fprintf(output, ";a OR c\n"); | 336 | fprintf(output, ";a OR c\n"); |
332 | fprintf(output, "pop rax\n"); | 337 | fprintf(output, "pop rax\n"); |
@@ -343,8 +348,8 @@ void gen_or(int left, int right, int idx) { | |||
343 | } | 348 | } |
344 | 349 | ||
345 | void gen_and(int left, int right, int idx) { | 350 | void gen_and(int left, int right, int idx) { |
346 | check_expected_types(left, INT,TAB); | 351 | check_expected_types(left, INT, TAB); |
347 | check_expected_types(right, INT,TAB); | 352 | check_expected_types(right, INT, TAB); |
348 | 353 | ||
349 | fprintf(output, ";a AND c\n"); | 354 | fprintf(output, ";a AND c\n"); |
350 | fprintf(output, "pop rax\n"); | 355 | fprintf(output, "pop rax\n"); |
@@ -361,8 +366,8 @@ void gen_and(int left, int right, int idx) { | |||
361 | } | 366 | } |
362 | 367 | ||
363 | void gen_eq(const char op[], int left, int right, int idx) { | 368 | void gen_eq(const char op[], int left, int right, int idx) { |
364 | check_expected_types(left, INT,TAB); | 369 | check_expected_types(left, INT, TAB); |
365 | check_expected_types(right, INT,TAB); | 370 | check_expected_types(right, INT, TAB); |
366 | 371 | ||
367 | fprintf(output, ";a EQ c\npop rax\npop rcx\ncmp rax,rcx\n"); | 372 | fprintf(output, ";a EQ c\npop rax\npop rcx\ncmp rax,rcx\n"); |
368 | 373 | ||
@@ -378,8 +383,8 @@ void gen_eq(const char op[], int left, int right, int idx) { | |||
378 | } | 383 | } |
379 | 384 | ||
380 | void gen_order(const char op[], int left, int right, int idx) { | 385 | void gen_order(const char op[], int left, int right, int idx) { |
381 | check_expected_types(left, INT,TAB); | 386 | check_expected_types(left, INT, TAB); |
382 | check_expected_types(right, INT,TAB); | 387 | check_expected_types(right, INT, TAB); |
383 | 388 | ||
384 | fprintf(output, ";a ORDER c\npop rcx\npop rax\ncmp rax,rcx\n"); | 389 | fprintf(output, ";a ORDER c\npop rcx\npop rax\ncmp rax,rcx\n"); |
385 | 390 | ||
@@ -399,8 +404,8 @@ void gen_order(const char op[], int left, int right, int idx) { | |||
399 | } | 404 | } |
400 | 405 | ||
401 | void gen_addsub(char op, int left, int right) { | 406 | void gen_addsub(char op, int left, int right) { |
402 | check_expected_types(left, INT,TAB); | 407 | check_expected_types(left, INT, TAB); |
403 | check_expected_types(right, INT,TAB); | 408 | check_expected_types(right, INT, TAB); |
404 | 409 | ||
405 | switch (op) { | 410 | switch (op) { |
406 | case '+': | 411 | case '+': |
@@ -415,8 +420,8 @@ void gen_addsub(char op, int left, int right) { | |||
415 | } | 420 | } |
416 | 421 | ||
417 | void gen_divstar(char op, int left, int right) { | 422 | void gen_divstar(char op, int left, int right) { |
418 | check_expected_types(left, INT,TAB); | 423 | check_expected_types(left, INT, TAB); |
419 | check_expected_types(right, INT,TAB); | 424 | check_expected_types(right, INT, TAB); |
420 | 425 | ||
421 | switch (op) { | 426 | switch (op) { |
422 | case '*': | 427 | case '*': |
@@ -433,7 +438,7 @@ void gen_divstar(char op, int left, int right) { | |||
433 | } | 438 | } |
434 | 439 | ||
435 | int gen_signed_expr(char op, int type) { | 440 | int gen_signed_expr(char op, int type) { |
436 | check_expected_types(type, INT,TAB); | 441 | check_expected_types(type, INT, TAB); |
437 | switch (op) { | 442 | switch (op) { |
438 | case '+': | 443 | case '+': |
439 | fprintf(output, ";+F\n"); | 444 | fprintf(output, ";+F\n"); |
@@ -449,7 +454,7 @@ int gen_signed_expr(char op, int type) { | |||
449 | } | 454 | } |
450 | 455 | ||
451 | int gen_negate_expr(int type) { | 456 | int gen_negate_expr(int type) { |
452 | check_expected_types(type, INT,TAB); | 457 | check_expected_types(type, INT, TAB); |
453 | fprintf(output, ";!F\npop rax\nxor rax,1\npush rax\n"); | 458 | fprintf(output, ";!F\npop rax\nxor rax,1\npush rax\n"); |