From 3e03d42ccb83ed0e7657719934736b7d0f03b1dc Mon Sep 17 00:00:00 2001 From: "Michael D. Lowis" Date: Tue, 11 May 2021 14:03:47 -0400 Subject: [PATCH] fully implemented first pass at array indexing with range checks --- cerise/backend/c99/codegen.c | 51 +++++++++++++++----------- cerise/backend/x86_64/codegen.c | 2 ++ cerise/inc/cerise.h | 26 +++----------- cerise/src/dump.c | 63 +++++++++++++++++++++++++++++++++ cerise/src/grammar.c | 7 ++-- cerise/tests/Module.m | 6 +++- 6 files changed, 108 insertions(+), 47 deletions(-) create mode 100644 cerise/src/dump.c diff --git a/cerise/backend/c99/codegen.c b/cerise/backend/c99/codegen.c index 89adf8c..9a1f738 100644 --- a/cerise/backend/c99/codegen.c +++ b/cerise/backend/c99/codegen.c @@ -47,7 +47,7 @@ static char* Operators[] = { // [IS] = ??? }; -static declare_var(Parser* p, Symbol* sym, int isref) +static void declare_var(Parser* p, Symbol* sym, int isref) { char name[8192]; if (sym->global) @@ -83,15 +83,12 @@ static int declare_temp(Parser* p, Type* type, int isref) char name[32]; int reg = p->curr_reg; snprintf(name, sizeof(name), "_T%d", reg); -// puts("TEMP"); Symbol sym = { .class = SYM_VAR, .name = name, .type = type, }; declare_var(p, &sym, isref); -// puts("END"); - p->curr_reg++; return reg; } @@ -120,16 +117,21 @@ static void load_var(Parser* p, Item* item) (isref ? '&' : ' '), p->name, item->imm.s); break; - case ITEM_REG: - /* nothing to do */ - break; - default: assert(!"bad load_var()"); } } } +static char* temp(Item* a) +{ + char name[32]; + snprintf(name, sizeof(name), "(%c_T%d)", + (a->mode == ITEM_INDEX ? '*' : ' '), + a->reg); + return strdup(name); +} + /* Operator Handling *****************************************************************************/ static void binary_op(Parser* p, int op, Item* a, Item* b) @@ -137,7 +139,7 @@ static void binary_op(Parser* p, int op, Item* a, Item* b) char* oper = Operators[op]; assert(oper); int dest_reg = declare_temp(p, a->type, 0); - printf(" = _T%d %s _T%d;\n", a->reg, oper, b->reg); + printf(" = %s %s %s;\n", temp(a), oper, temp(b)); a->reg = dest_reg; } @@ -146,7 +148,7 @@ static void unary_op(Parser* p, int op, Item* a) char* oper = Operators[op]; assert(oper); int dest_reg = declare_temp(p, a->type, 0); - printf(" = %s _T%d;\n", oper, a->reg); + printf(" = %s %s;\n", oper, temp(a)); a->reg = dest_reg; } @@ -257,15 +259,13 @@ void codegen_binop(Parser* p, int op, Item* a, Item* b) void codegen_store(Parser* p, Item* a, Item* b) { -// item_dump(a); -// item_dump(b); if (a->mode == ITEM_MVAR && b->reg == 0) { printf(" %s_%s = %lld;\n", p->name, a->imm.s, b->imm.i); } else if (a->mode == ITEM_MVAR) { - printf(" %s_%s = _T%d;\n", p->name, a->imm.s, b->reg); + printf(" %s_%s = %s;\n", p->name, a->imm.s, temp(b)); } else if (a->mode == ITEM_VAR && b->reg == 0) { @@ -273,12 +273,12 @@ void codegen_store(Parser* p, Item* a, Item* b) } else if (a->mode == ITEM_VAR) { - printf(" %s = _T%d;\n", a->imm.s, b->reg); + printf(" %s = %s;\n", a->imm.s, temp(b)); } else if (a->mode == ITEM_INDEX) { load_var(p, b); - printf(" _T%d = _T%d;\n", a->reg, b->reg); + printf(" %s = %s;\n", temp(a), temp(b)); } else { @@ -289,7 +289,7 @@ void codegen_store(Parser* p, Item* a, Item* b) void codegen_if(Parser* p, Item* item) { load_var(p, item); - printf(" if (_T%d) {\n", item->reg); + printf(" if (%s) {\n", temp(item)); } void codegen_else(Parser* p, Item* item) @@ -320,7 +320,7 @@ void codegen_call(Parser* p, Item* item, Item* args) printf(" = %s(", item->imm.s); while (args) { - printf("_T%d", args->reg); + printf("%s", temp(args)); if (args->next) { printf(", "); @@ -333,17 +333,23 @@ void codegen_call(Parser* p, Item* item, Item* args) void codegen_setarg(Parser* p, Item* item, bool firstarg) { + (void)firstarg; load_var(p, item); } void codegen_return(Parser* p, Item* item) { load_var(p, item); - printf(" return _T%d;\n", item->reg); + printf(" return %s;\n", temp(item)); } void codegen_index(Parser* p, Item* array, Item* index) { + /* load array and index if not already */ + load_var(p, index); + load_var(p, array); + + /* perform range checking */ if (index->mode == ITEM_CONST) { if (index->type->form != FORM_INT) @@ -359,12 +365,15 @@ void codegen_index(Parser* p, Item* array, Item* index) error(p, "negative array index"); } } + else + { + printf(" __CHECK_RANGE(%s < %d);\n", temp(index), array->type->size); + } - load_var(p, index); - load_var(p, array); + /* emit the operation */ array->type = array->type->base; array->mode = ITEM_INDEX; int dest_reg = declare_temp(p, array->type, 1); - printf(" = _T%d[_T%d]\;\n", array->reg, index->reg); + printf(" = &%s[%s];\n", temp(array), temp(index)); array->reg = dest_reg; } diff --git a/cerise/backend/x86_64/codegen.c b/cerise/backend/x86_64/codegen.c index 651f515..db4efab 100644 --- a/cerise/backend/x86_64/codegen.c +++ b/cerise/backend/x86_64/codegen.c @@ -202,7 +202,9 @@ static void load_var(Parser* p, Item* item) next_reg(p); break; + case ITEM_INDEX: case ITEM_REG: + default: /* nothing to do */ break; } diff --git a/cerise/inc/cerise.h b/cerise/inc/cerise.h index f721565..f1b76e8 100644 --- a/cerise/inc/cerise.h +++ b/cerise/inc/cerise.h @@ -136,27 +136,6 @@ typedef struct { int level; } Parser; -static inline void item_dump(Item* a) -{ - printf("// Item M:%d R:%d ", a->mode, a->reg); - if (a->mode == ITEM_MVAR) - { - printf(" %s", a->imm.s); - } - else - { - if (a->type->form == FORM_INT) - { - printf("%lld", a->imm.i); - } - else if (a->type->form == FORM_REAL) - { - printf("%f", a->imm.f); - } - } - puts(""); -} - // src/stdlib.c void fatal(char* estr); void* emalloc(size_t size); @@ -203,6 +182,11 @@ int items_const(Item* a, Item* b); void const_binop(int op, Item* a, Item* b); void const_unop(Parser* p, int op, Item* a); +// src/dump.c +void dump_item(Item* a); +void dump_symbol(Symbol* a); +void dump_type(Type* a); + /* Backend Code Generation *****************************************************************************/ extern Type BoolType, IntType, RealType, StringType; diff --git a/cerise/src/dump.c b/cerise/src/dump.c new file mode 100644 index 0000000..e0399a6 --- /dev/null +++ b/cerise/src/dump.c @@ -0,0 +1,63 @@ +#include + +void dump_item(Item* a) +{ + printf("// Item M:%d R:%d ", a->mode, a->reg); + if (a->mode == ITEM_MVAR) + { + printf(" %s", a->imm.s); + } + else + { + if (a->type->form == FORM_INT) + { + printf("%lld", a->imm.i); + } + else if (a->type->form == FORM_REAL) + { + printf("%f", a->imm.f); + } + } + puts(""); +} + +void dump_symbol(Symbol* a) +{ + (void)a; +} + +void dump_type(Type* a) +{ + printf("// Type: "); + for (; a; a = a->base) + { + switch (a->form) + { + case FORM_BOOL: + printf("Bool"); + break; + + case FORM_INT: + printf("Int"); + break; + + case FORM_REAL: + printf("Real"); + break; + + case FORM_ARRAY: + printf("array %d of ", a->size); + break; + + case FORM_STRING: + printf("String"); + break; + + default: + printf("?"); + break; + } + } + puts(""); +} + diff --git a/cerise/src/grammar.c b/cerise/src/grammar.c index a5bb9f0..2bbdf9b 100644 --- a/cerise/src/grammar.c +++ b/cerise/src/grammar.c @@ -119,11 +119,10 @@ RULE(designator) Item index = {0}; expect(p, '['); expression(p, &index); - printf("%d\n", item->type->form ); if (item->type->form == FORM_ARRAY) { codegen_index(p, item, &index); - item->type = item->type->base; +// item->type = item->type->base; } else { @@ -720,8 +719,8 @@ static void parse_init(char* fname, char* string) static void parse_rule(void (*rule)(Parser*, Item*), Item* item, char* string) { - puts(""); - printf("%s\n", string); +// puts(""); +// printf("%s\n", string); parse_init("test_input", string); rule(&Ctx, (item ? item : &(Item){0})); } diff --git a/cerise/tests/Module.m b/cerise/tests/Module.m index 77ba511..7e69119 100644 --- a/cerise/tests/Module.m +++ b/cerise/tests/Module.m @@ -107,6 +107,10 @@ begin # c = Foo(1,2); # e[0] = 1; # Foo(1,2); - e[2][1] = 1; +# e[2][1] = 1 + e[2][1]; # e[b] = 1; + e[1][2] = 1; + c = e[1][c]; end + +# _T5 _T10 \ No newline at end of file -- 2.49.0