implement arithmetic operations asm generation

This commit is contained in:
Arnaud Vergnet 2021-04-06 16:19:44 +02:00
parent 96ab1bf771
commit 74e97fe963
11 changed files with 152 additions and 69 deletions

View file

@ -5,10 +5,10 @@ CC = gcc
all: compilateur test all: compilateur test
test: symbol_table.test.c symbol_table.c symbol_table.h test: symbol_table.test.c symbol_table.c symbol_table.h
$(CC) -o test symbol_table.test.c symbol_table.c $(CC) -g -o test symbol_table.test.c symbol_table.c
compilateur: as.tab.c lex.yy.c symbol_table.c symbol_table.h asm_instructions.c asm_instructions.h compilateur: as.tab.c lex.yy.c symbol_table.c symbol_table.h asm_instructions.c asm_instructions.h yacc_util.c yacc_util.h
$(CC) -o compilateur as.tab.c lex.yy.c symbol_table.c asm_instructions.c $(CC) -o compilateur as.tab.c lex.yy.c symbol_table.c asm_instructions.c yacc_util.c
as.tab.c: as.y as.tab.c: as.y
$(YACC) as.y $(YACC) as.y

22
al.lex
View file

@ -1,4 +1,6 @@
%{ %{
#include "asm_instructions.h"
#include "symbol_table.h"
#include "as.tab.h" #include "as.tab.h"
%} %}
@ -11,10 +13,22 @@ D [0-9]
return tNB; return tNB;
} }
"+" { return tADD; } "+" {
"-" { return tSUB; } yylval.instruction = ADD;
"*" { return tMUL; } return tADD;
"/" { return tDIV; } }
"-" {
yylval.instruction = SOU;
return tSUB;
}
"*" {
yylval.instruction = MUL;
return tMUL;
}
"/" {
yylval.instruction = DIV;
return tDIV;
}
"=" { return tEQ; } "=" { return tEQ; }
"(" { return tPO; } "(" { return tPO; }
")" { return tPF; } ")" { return tPF; }

34
as.y
View file

@ -2,23 +2,28 @@
#include "stdio.h" #include "stdio.h"
#include "stdlib.h" #include "stdlib.h"
#include "symbol_table.h" #include "symbol_table.h"
#include "asm_instructions.h"
#include "yacc_util.h"
enum Type current_type = TYPE_INT; enum Type current_type = TYPE_INT;
SymbolTable symbol_table; SymbolTable symbol_table;
InstructionTable instruction_table;
%} %}
%union { %union {
char* symbol_name; char* symbol_name;
SymbolItem* symbol;
int nombre; int nombre;
Instruction instruction;
} }
%token<nombre> tNB %token<nombre> tNB
%token tADD %token<instruction> tADD
%token tSUB %token<instruction> tSUB
%token tMUL %token<instruction> tMUL
%token tDIV %token<instruction> tDIV
%token tPO %token tPO
%token tPF %token tPF
%token tPV %token tPV
@ -50,7 +55,7 @@ SymbolTable symbol_table;
%left tSUB %left tSUB
%left tMUL %left tMUL
%left tDIV %left tDIV
// %type<nombre> E %type<symbol> E
%% %%
@ -71,13 +76,20 @@ Instructions : Instruction Instructions | { printf("Instructions\n"); } ;
Instruction : Aff | Printf { printf("Instruction\n"); } ; Instruction : Aff | Printf { printf("Instruction\n"); } ;
Aff : tID tEQ E tPV { mark_symbol_initialized(&symbol_table, $1); } ; Aff : tID tEQ E tPV { write_affectation(&symbol_table, &instruction_table, $1, $3); } ;
E : tNB { printf("%d\n", $1); } | tID | E tADD E | E tMUL E | E tSUB E | E tDIV E | tPO E tPF | tSUB E ; E : tNB { $$ = init_temp_symbol(&symbol_table, &instruction_table, $1); }
| tID { $$ = get_symbol_item(&symbol_table, $1); }
| E tADD E {$$ = write_op(&symbol_table, &instruction_table, $2, $1, $3); }
| E tMUL E { $$ = write_op(&symbol_table, &instruction_table, $2, $1, $3); }
| E tSUB E { $$ = write_op(&symbol_table, &instruction_table, $2, $1, $3); }
| E tDIV E { $$ = write_op(&symbol_table, &instruction_table, $2, $1, $3); }
| tPO E tPF { $$ = $2; }
| tSUB E { $$ = write_negation(&symbol_table, &instruction_table, $2); } ;
Declarations : | Declaration Declarations { printf("Declarations\n"); } ; Declarations : | Declaration Declarations ;
Declaration : DeclarationInt | DeclarationConst { printf("Declaration\n"); } ; Declaration : DeclarationInt | DeclarationConst ;
DeclarationInt : tINT { current_type = TYPE_INT; } DeclarationBody tPV ; DeclarationInt : tINT { current_type = TYPE_INT; } DeclarationBody tPV ;
@ -162,6 +174,7 @@ On suppose que E est tout le temps une vt, donc on génère tout le temps le mê
void init() { void init() {
init_table(&symbol_table); init_table(&symbol_table);
init_instruction_table(&instruction_table);
} }
void yyerror(char const* err) { void yyerror(char const* err) {
@ -173,4 +186,7 @@ void main(void) {
init(); init();
yyparse(); yyparse();
print_table(&symbol_table); print_table(&symbol_table);
FILE *f = fopen("instruction_table.txt", "w+");
write_instruction_table(&instruction_table, f);
fclose(f);
} }

View file

@ -1,5 +1,20 @@
#include "asm_instructions.h" #include "asm_instructions.h"
char* instructions_labels[12] = {
"ADD",
"MUL",
"SOU",
"DIV",
"COP",
"AFC",
"JMP",
"JMF",
"INF",
"SUP",
"EQU",
"PRI"
};
void init_instruction_table(InstructionTable *table) { void init_instruction_table(InstructionTable *table) {
table->index = 0; table->index = 0;
} }
@ -26,5 +41,5 @@ void write_instruction_table(InstructionTable *table, FILE *file) {
} }
void write_instruction(InstructionItem *item, FILE *file) { void write_instruction(InstructionItem *item, FILE *file) {
fprintf(file, "%s %d %d %d", instructions_labels[item->instruction], item->arg1, item->arg2, item->arg3); fprintf(file, "%s %d %d %d\n", instructions_labels[item->instruction], item->arg1, item->arg2, item->arg3);
} }

View file

@ -8,7 +8,7 @@
typedef enum Instruction { typedef enum Instruction {
ADD, ADD,
MUL, MUL,
SUO, SOU,
DIV, DIV,
COP, COP,
AFC, AFC,
@ -20,20 +20,7 @@ typedef enum Instruction {
PRI PRI
} Instruction; } Instruction;
char* instructions_labels[12] = { char* instructions_labels[12];
"ADD",
"MUL",
"SUO",
"DIV",
"COP",
"AFC",
"JMP",
"JMF",
"INF",
"SUP",
"EQU",
"PRI"
};
typedef struct InstructionItem { typedef struct InstructionItem {

View file

@ -8,6 +8,13 @@ void init_table(SymbolTable *table) {
table->temp_index = SYMBOL_TABLE_SIZE - 1; table->temp_index = SYMBOL_TABLE_SIZE - 1;
} }
void init_symbol_item(SymbolItem *symbol_item, size_t name_size) {
symbol_item->type = 0;
symbol_item->name = malloc(name_size);
symbol_item->address = 0;
symbol_item->init = 0;
}
int has_symbol(SymbolTable* table, char *name) { int has_symbol(SymbolTable* table, char *name) {
for (int i = 0; i < table->index; i++) { for (int i = 0; i < table->index; i++) {
if (strcmp(table->table[i].name, name) == 0) { if (strcmp(table->table[i].name, name) == 0) {
@ -30,6 +37,7 @@ int add_symbol(SymbolTable *table, enum Type type, char *name) {
return -1; return -1;
} }
SymbolItem newItem; SymbolItem newItem;
init_symbol_item(&newItem, strlen(name));
newItem.type = type; newItem.type = type;
newItem.name = name; newItem.name = name;
newItem.address = table->index; newItem.address = table->index;
@ -40,26 +48,20 @@ int add_symbol(SymbolTable *table, enum Type type, char *name) {
return 0; return 0;
} }
int add_temp_symbol(SymbolTable* table, enum Type type, char *name) { const SymbolItem* add_temp_symbol(SymbolTable* table, enum Type type) {
if (table->temp_index < table->index) { if (table->temp_index < table->index) {
return -2; return NULL;
}
if (has_symbol(table, name)) {
return -1;
}
if (name[0] != '_') {
return -3;
} }
SymbolItem newItem; SymbolItem *newItem = &table->table[table->temp_index];
newItem.type = type; init_symbol_item(newItem, 10);
newItem.name = name; newItem->type = type;
newItem.address = table->temp_index; sprintf(newItem->name, "_temp%d", table->temp_index);
newItem.init = 0; newItem->address = table->temp_index;
newItem->init = 0;
table->table[table->temp_index] = newItem;
table->temp_index--; table->temp_index--;
return 0; return newItem;
} }
int mark_symbol_initialized(SymbolTable *table, char *name) { int mark_symbol_initialized(SymbolTable *table, char *name) {
@ -107,7 +109,7 @@ void print_item(struct SymbolItem *item) {
} }
} }
SymbolItem *get_symbol_item(SymbolTable *table, char *name) { SymbolItem *get_symbol_item(SymbolTable *table, const char *name) {
for (int i = 0; i < table->index; i++) { for (int i = 0; i < table->index; i++) {
if (strcmp(table->table[i].name, name) == 0) { if (strcmp(table->table[i].name, name) == 0) {
return &table->table[i]; return &table->table[i];

View file

@ -1,6 +1,8 @@
#ifndef SYMBOL_TABLE_H_INCLUDED #ifndef SYMBOL_TABLE_H_INCLUDED
#define SYMBOL_TABLE_H_INCLUDED #define SYMBOL_TABLE_H_INCLUDED
#include <stddef.h>
#define SYMBOL_TABLE_SIZE 100 #define SYMBOL_TABLE_SIZE 100
enum Type { enum Type {
@ -31,6 +33,13 @@ typedef struct SymbolTable {
*/ */
void init_table(SymbolTable *table); void init_table(SymbolTable *table);
/**
* Initializes the symbol
*
* @param table
*/
void init_symbol_item(SymbolItem *symbol_item, size_t name_size);
/** /**
* Checks if the given symbol is in the table * Checks if the given symbol is in the table
* *
@ -57,10 +66,9 @@ int add_symbol(SymbolTable* table, enum Type type, char *name);
* @param table * @param table
* @param type * @param type
* @param name * @param name
* @return 0 on success, -1 if the symbol already exists, -2 if the table is full * @return 0 on success, -1 if the table is full
* -3 if the name doesn't start by _
*/ */
int add_temp_symbol(SymbolTable* table, enum Type type, char *name); const SymbolItem* add_temp_symbol(SymbolTable* table, enum Type type);
/** /**
* Marks the given symbol as initialized * Marks the given symbol as initialized
@ -100,6 +108,6 @@ char* type_to_string(enum Type type);
* @param name * @param name
* @return the item if found, NULL otherwise * @return the item if found, NULL otherwise
*/ */
SymbolItem *get_symbol_item(SymbolTable* table, char *name); SymbolItem *get_symbol_item(SymbolTable* table, const char *name);
#endif /* !SYMBOL_TABLE_H_INCLUDED */ #endif /* !SYMBOL_TABLE_H_INCLUDED */

View file

@ -1,6 +1,7 @@
#include "symbol_table.h" #include "symbol_table.h"
#include <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
#include <string.h>
int main() { int main() {
int err; int err;
@ -33,23 +34,17 @@ int main() {
printf("Mark b initialized\n"); printf("Mark b initialized\n");
assert(err == -1); assert(err == -1);
err = add_temp_symbol(&table, TYPE_INT, "_temp1"); const SymbolItem* var1 = add_temp_symbol(&table, TYPE_INT);
printf("Add _temp1 temporary variable\n"); printf("Add _temp99 temporary variable\n");
assert(err == 0); assert(strcmp(var1->name, "_temp99") == 0);
err = add_temp_symbol(&table, TYPE_INT, "_temp2"); const SymbolItem* var2 = add_temp_symbol(&table, TYPE_INT);
printf("Add _temp2 temporary variable\n"); printf("Add _temp98 temporary variable\n");
assert(err == 0); assert(strcmp(var2->name, "_temp98") == 0);
err = add_temp_symbol(&table, TYPE_INT, "_temp1");
printf("Add _temp1 temporary variable\n");
assert(err == -1);
err = add_temp_symbol(&table, TYPE_INT, "temp1");
printf("Add temp1 temporary variable\n");
assert(err == -3);
item = get_symbol_item(&table, "_temp1"); item = get_symbol_item(&table, "_temp98");
printf("_temp1:\n"); printf("_temp98:\n");
print_item(item); print_item(item);
item = get_symbol_item(&table, "_temp5"); item = get_symbol_item(&table, "_temp0");
printf("_temp5:\n"); printf("_temp5:\n");
print_item(item); print_item(item);

4
test.c
View file

@ -2,6 +2,6 @@ int main(){
int x, y, z; int x, y, z;
const PL5_op, b, c; const PL5_op, b, c;
printf(x); printf(x);
x = 3 + 2; x = 2;
y = 3; y = 3 + 3 + x;
} }

30
yacc_util.c Normal file
View file

@ -0,0 +1,30 @@
#include "yacc_util.h"
void write_affectation(SymbolTable* symbol_table, InstructionTable *instruction_table, char* symbol_dest, SymbolItem* src) {
mark_symbol_initialized(symbol_table, symbol_dest);
SymbolItem *dest = get_symbol_item(symbol_table, symbol_dest);
add_instruction(instruction_table, COP, src->address, dest->address, 0);
}
const SymbolItem* write_op(SymbolTable* symbol_table, InstructionTable *instruction_table, Instruction instruction, SymbolItem *op1, SymbolItem *op2) {
const SymbolItem* dest = add_temp_symbol(symbol_table, TYPE_INT);
add_instruction(instruction_table, instruction, dest->address, op1->address, op2->address);
return dest;
}
const SymbolItem* write_negation(SymbolTable* symbol_table, InstructionTable *instruction_table, SymbolItem *op2) {
// Create temp variable with 0
const SymbolItem* op1 = init_temp_symbol(symbol_table, instruction_table, 0);
const SymbolItem* dest = add_temp_symbol(symbol_table, TYPE_INT);
// Make the 0 - variable operation
add_instruction(instruction_table, SOU, dest->address, op1->address, op2->address);
return dest;
}
const SymbolItem* init_temp_symbol(SymbolTable* symbol_table, InstructionTable *instruction_table, int constant) {
const SymbolItem* dest = add_temp_symbol(symbol_table, TYPE_INT);
add_instruction(instruction_table, AFC, dest->address, constant, 0);
return dest;
}

16
yacc_util.h Normal file
View file

@ -0,0 +1,16 @@
#include "symbol_table.h"
#include "asm_instructions.h"
#ifndef COMPILATOR_2000_YACC_UTIL_H
#define COMPILATOR_2000_YACC_UTIL_H
void write_affectation(SymbolTable* symbolTable, InstructionTable *instructionTable, char* symbol_dest, SymbolItem* src);
const SymbolItem* write_op(SymbolTable* symbol_table, InstructionTable *instruction_table, Instruction instruction, SymbolItem *op1, SymbolItem *op2);
const SymbolItem* write_negation(SymbolTable* symbol_table, InstructionTable *instruction_table, SymbolItem *op2);
const SymbolItem* init_temp_symbol(SymbolTable* symbol_table, InstructionTable *instruction_table, int constant);
#endif //COMPILATOR_2000_YACC_UTIL_H