diff --git a/c/include/expr.h b/c/include/expr.h index 4661fd5..7417d5c 100644 --- a/c/include/expr.h +++ b/c/include/expr.h @@ -26,6 +26,7 @@ struct expr { struct expr * expr_create(expr_t kind, struct label *l, struct oper *o, struct ttk_register *f_arg, struct value *s_arg, struct comment *c, struct expr *n); int expr_print(struct expr *e); +int expr_print_intel_asm(struct expr *e); void expr_copy(struct expr *orig, struct expr *copy); diff --git a/c/include/label.h b/c/include/label.h index ad71093..0ec4611 100644 --- a/c/include/label.h +++ b/c/include/label.h @@ -15,6 +15,7 @@ struct label { }; struct label * label_create(label_t kind, char* name, int value); +int label_print_intel_asm(struct label *l); int label_print(struct label *l); struct label * label_create_const(char* name); diff --git a/c/include/oper.h b/c/include/oper.h index b1106d7..1080afb 100644 --- a/c/include/oper.h +++ b/c/include/oper.h @@ -20,6 +20,7 @@ struct oper { struct oper * oper_create(oper_t kind, char* oper_name); int oper_print(struct oper *o); +int oper_print_intel_asm(struct oper *o); struct oper * oper_create_data(char* oper_name); struct oper * oper_create_arithmetic(char* oper_name); diff --git a/c/include/program.h b/c/include/program.h index e010070..f64ecd8 100644 --- a/c/include/program.h +++ b/c/include/program.h @@ -1,4 +1,5 @@ #include "expr.h" int program_print(struct expr *program); +int program_print_intel_asm(struct expr *program); void program_free(struct expr *program); diff --git a/c/include/ttk_register.h b/c/include/ttk_register.h index 96e7d4f..bb60213 100644 --- a/c/include/ttk_register.h +++ b/c/include/ttk_register.h @@ -18,6 +18,7 @@ struct ttk_register * ttk_register_create_register(char* name); struct ttk_register * ttk_register_create_stack_register(char* name); int ttk_register_print(struct ttk_register *ttk_reg); +int ttk_register_print_intel_asm(struct ttk_register *ttk_reg); void ttk_register_free(struct ttk_register *ttk_reg); diff --git a/c/include/value.h b/c/include/value.h index 6052a7c..c1c758e 100644 --- a/c/include/value.h +++ b/c/include/value.h @@ -50,7 +50,10 @@ struct pure_value * pure_value_create_label(struct label *l); struct pure_value * pure_value_create(value_t kind, struct ttk_register *ttk_reg, int num, struct label *l); addr_mode_t parse_addr_mode(char* addr_mode); +int pure_value_print(struct pure_value *p_v); int value_print(struct value *v); +int pure_value_print_intel_asm(struct pure_value *p_v); +int value_print_intel_asm(struct value *v); void value_free(struct value *v); diff --git a/c/src/expr.c b/c/src/expr.c index 9f6ce5b..20cd97f 100644 --- a/c/src/expr.c +++ b/c/src/expr.c @@ -1,5 +1,6 @@ #include #include +#include #include "error.h" #include "expr.h" @@ -61,6 +62,98 @@ struct expr *expr_create_comment(struct comment *c) return expr_create(COMMENT, NULL, NULL, NULL, NULL, c, NULL); } +int expr_print_intel_asm(struct expr *e) +{ + // TODO: Delve deeper into this. This works a bit differently than ttk91 + // For ex. LOAD R1, =2(R2) needs to be translated into multiple instructions in assembly. + + if (!e) + return VARIABLE_NULL; + + switch (e->kind) + { + case INSTRUCTION: + { + if (e->label) + printf("\"LABEL\""); + + // operator + int err = oper_print_intel_asm(e->oper); + if (err!=0) + return err; + + printf(" "); + + // If oper is STORE switch arguments around + if (e->oper && strcasecmp("STORE", e->oper->oper_name) == 0) + { + // Second argument + int err = value_print_intel_asm(e->second_arg); + if (err!=0) + return err; + + printf(", "); + + // First argument + err = ttk_register_print_intel_asm(e->first_arg); + if (err!=0) + return err; + } + else + { + // first argument + err = ttk_register_print_intel_asm(e->first_arg); + if (err!=0) + return err; + + printf(", "); + + // second argument + err = value_print_intel_asm(e->second_arg); + if (err!=0) + return err; + } + + printf("\n"); + break; + } + + case LABEL_DEF: + { + int err = label_print_intel_asm(e->label); + if (err) + return err; + printf(" "); + + err = oper_print_intel_asm(e->oper); + if (err) + return err; + printf(" "); + + if (!e->second_arg) + return VARIABLE_NULL; + err = pure_value_print_intel_asm(e->second_arg->value); + if (err) + return err; + + printf("\n"); + break; + } + + case COMMENT: + { + // Comments are skipped. + break; + } + + default: + printf("NOT IMPLEMENTED %d\n", e->kind); + break; + } + + return 0; +} + int expr_print(struct expr *e) { if (!e) diff --git a/c/src/label.c b/c/src/label.c index 421c0fc..6310aad 100644 --- a/c/src/label.c +++ b/c/src/label.c @@ -23,6 +23,11 @@ struct label * label_create_const(char* name) { return label_create(LABEL_ struct label * label_create_const_sys(char* name) { return label_create(LABEL_CONST, name, 0); } // FIXME value struct label * label_create_tag(char* name) { return label_create(LABEL_TAG, name, 0); } // FIXME also this +int label_print_intel_asm(struct label *l) +{ + return label_print(l); +} + int label_print(struct label *l) { if (!l->name) diff --git a/c/src/main.c b/c/src/main.c index a4dfbb6..1191ccb 100644 --- a/c/src/main.c +++ b/c/src/main.c @@ -4,9 +4,9 @@ #include "token.h" #include "program.h" -//#define FILENAME "../docs/example-file-harder.k91" -//#define FILENAME "../docs/example-file.k91" -#define FILENAME "../docs/example-file-simple.k91" +// #define FILENAME "../docs/example-file-harder.k91" +#define FILENAME "../docs/example-file.k91" +// #define FILENAME "../docs/example-file-simple.k91" // scanner extern FILE *yyin; @@ -14,13 +14,19 @@ extern int yylex(); extern char *yytext; // parser -extern int yyparse(); +extern int yyparse(struct expr*); -int main() +int main(int argc, char **argv) { - yyin = fopen(FILENAME, "r"); + if (argc <= 1) + { + printf("Using default file %s\n", FILENAME); + yyin = fopen(FILENAME, "r"); + } + else + yyin = fopen(argv[1], "r"); if (!yyin) { printf("Couldn't open file\n"); @@ -30,21 +36,37 @@ int main() struct expr *parse_result = malloc(sizeof(*parse_result)); if (!parse_result) { + fclose(yyin); printf("ERROR: Failed to allocate memory for parse_result.\n"); return ALLOC_FAILED; } - if (yyparse(parse_result) == 0) { - printf("Parse succesful :)\n"); - } else { + if (yyparse(parse_result) != 0) + { + fclose(yyin); program_free(parse_result); + printf("Error parsing the file\n"); return PARSE_ERROR; } + printf("Parse successful\n"); + + fclose(yyin); int err = program_print(parse_result); if (err!=0) + { + printf("Error printing program\n"); return err; + } + + printf("\n"); + err = program_print_intel_asm(parse_result); + if (err!=0) + { + printf("Error printing program in intel asm.\n"); + return err; + } program_free(parse_result); // TODO handle errors with assertions diff --git a/c/src/oper.c b/c/src/oper.c index 316cdf3..6c3e078 100644 --- a/c/src/oper.c +++ b/c/src/oper.c @@ -36,6 +36,87 @@ int oper_print(struct oper *o) return 0; } +int oper_print_intel_asm(struct oper *o) +{ + if (!o) + { + printf("ERROR: Null oper given.\n"); + return VARIABLE_NULL; + } + + switch (o->kind) + { + case OPER_DATA: + { + if (strcasecmp("LOAD", o->oper_name) == 0) + printf("mov"); + else if (strcasecmp("STORE", o->oper_name) == 0) + printf("mov"); + else if (strcasecmp("IN", o->oper_name) == 0) + printf("\"IN\""); + else if (strcasecmp("OUT", o->oper_name) == 0) + printf("\"OUT\""); + break; + } + + case OPER_AR: + { + if (strcasecmp("ADD", o->oper_name) == 0) + printf("add"); + else if (strcasecmp("SUB", o->oper_name) == 0) + printf("sub"); + else if (strcasecmp("MUL", o->oper_name) == 0) + printf("mul"); + else if (strcasecmp("DIV", o->oper_name) == 0) + printf("div"); + else + printf("\"%s\"", o->oper_name); + break; + } + + case OPER_COMPILER: + { + if (strcasecmp("DEF", o->oper_name) == 0) + printf("\"%s\"", o->oper_name); + else + printf("dw"); + break; + } + + case OPER_LOGIC: + { + printf("\"%s\"", o->oper_name); + break; + } + + case OPER_BRANCH: + { + printf("\"%s\"", o->oper_name); + break; + } + + case OPER_STACK: + { + printf("\"%s\"", o->oper_name); + break; + } + + case OPER_SYS: + { + printf("\"%s\"", o->oper_name); + break; + } + + default: + { + return SWITCH_NOT_MATCHED; + } + } + + + return 0; +} + void oper_free(struct oper *o) { if (o->oper_name) free(o->oper_name); diff --git a/c/src/program.c b/c/src/program.c index 34f3a26..75a56c4 100644 --- a/c/src/program.c +++ b/c/src/program.c @@ -18,6 +18,21 @@ int program_print(struct expr *program) } +int program_print_intel_asm(struct expr *program) +{ + struct expr *current = program; + + while (current != NULL) + { + int err = expr_print_intel_asm(current); + if (err != 0) + return err; + current = current->next; + } + + return 0; +} + void program_free(struct expr *program) { struct expr *current = program; diff --git a/c/src/ttk_register.c b/c/src/ttk_register.c index 907fcec..50402c8 100644 --- a/c/src/ttk_register.c +++ b/c/src/ttk_register.c @@ -68,6 +68,48 @@ int parse_register_num(char* name, ttk_register_t kind) return value; } +int ttk_register_print_intel_asm(struct ttk_register *ttk_reg) +{ + // EAX, EBX, ECX, EDX, ESP, EBP, ESI, EDI + if (!ttk_reg || !ttk_reg->id) + { + printf("ttk_register missing while trying to print it.\n"); + return VARIABLE_NULL; + } + + switch (ttk_reg->id) + { + case 1: + printf("eax"); + break; + case 2: + printf("ebx"); + break; + case 3: + printf("ecx"); + break; + case 4: + printf("edx"); + break; + case 5: + printf("esp"); + break; + case 6: + printf("ebp"); + break; + case 7: + printf("esi"); + break; + case 0: + printf("edi"); // TODO: this is possibly not correct + break; + default: + printf("ERROR: No matching register\n"); + return SWITCH_NOT_MATCHED; + } + return 0; +} + int ttk_register_print(struct ttk_register *ttk_reg) { if (!ttk_reg || !ttk_reg->id) diff --git a/c/src/value.c b/c/src/value.c index bf45d7a..b5f9fe9 100644 --- a/c/src/value.c +++ b/c/src/value.c @@ -76,6 +76,77 @@ addr_mode_t parse_addr_mode(char* addr_mode) return DIRECT; } +int pure_value_print_intel_asm(struct pure_value *p_v) +{ + return pure_value_print(p_v); +} + +int value_print_intel_asm(struct value *v) +{ + if (!v) + { + printf("ERROR: Value not defined.\n"); + return VARIABLE_NULL; + } + + if (v->indexing_mode == NONE) + { + switch (v->addr_mode) + { + case IMMEDIATE: + { + int err = pure_value_print_intel_asm(v->value); + if (err!=0) + return err; + break; + } + + case DIRECT: + case INDIRECT: + { + if (v->value && v->value->kind != NUMBER) + { + int err = pure_value_print_intel_asm(v->value); + if (err!=0) + return err; + } + else { + printf("["); + int err = pure_value_print_intel_asm(v->value); + if (err!=0) + return err; + printf("]"); + } + + break; + } + } + } + else if (v->indexing_mode == INDEXED) + { + switch (v->addr_mode) + { + case IMMEDIATE: + { + printf("["); + int err = ttk_register_print_intel_asm(v->index_register); + if (err!=0) + return err; + + printf(" + "); + + err = pure_value_print_intel_asm(v->value); + if (err!=0) + return err; + printf("]"); + } + } + } + else + return SWITCH_NOT_MATCHED; + + return 0; +} int pure_value_print(struct pure_value *p_v) {