From cc36eefcb731689b5e39e414a764021793bbd55b Mon Sep 17 00:00:00 2001 From: mike lowis Date: Tue, 25 May 2021 20:43:09 -0400 Subject: [PATCH] implemented record types and record member access --- cerise/backend/c99/codegen.c | 149 +++++++++++++++++++++++++++----- cerise/backend/test/codegen.c | 6 ++ cerise/backend/x86_64/codegen.c | 5 ++ cerise/inc/cerise.h | 3 +- cerise/src/grammar.c | 17 +++- cerise/tests/Module.m | 8 +- 6 files changed, 163 insertions(+), 25 deletions(-) diff --git a/cerise/backend/c99/codegen.c b/cerise/backend/c99/codegen.c index 1db17e9..4d22b4a 100644 --- a/cerise/backend/c99/codegen.c +++ b/cerise/backend/c99/codegen.c @@ -23,9 +23,9 @@ Type StringType = { }; static char* TypeNames[FORM_COUNT] = { - [FORM_BOOL] = "_Bool", - [FORM_INT] = "long", - [FORM_REAL] = "double", + [FORM_BOOL] = "Bool", + [FORM_INT] = "Int", + [FORM_REAL] = "Real", [FORM_STRING] = "char*" }; @@ -47,7 +47,35 @@ static char* Operators[] = { // [IS] = ??? }; -static void declare_var(Parser* p, Symbol* sym, int isref) +char* typetoptr(Type* type) +{ + if (type->form == FORM_BOOL) + { + return "Bool*"; + } + else if (type->form == FORM_INT) + { + return "Int*"; + } + else if (type->form == FORM_REAL) + { + return "Real*"; + } +// else if (type->form == FORM_ARRAY) +// { +// return "(*)[]"; +// } +// else if (type->form == FORM_RECORD) +// { +// return +// } + else + { + assert(!"unimplemented type output"); + } +} + +static void make_var(Parser* p, Symbol* sym, int isref) { char name[8192]; if (sym->global) @@ -57,7 +85,6 @@ static void declare_var(Parser* p, Symbol* sym, int isref) } else { - printf(" "); snprintf(name, sizeof(name), "(%c%s)", (char)(isref ? '*' : ' '), sym->name); } @@ -72,12 +99,26 @@ static void declare_var(Parser* p, Symbol* sym, int isref) printf("[%d]", type->size); } } + else if (sym->type->form == FORM_RECORD) + { + printf("char %s[%d]", name, sym->type->size); + } else { printf("%s %s", TypeNames[sym->type->form], name); } } +static void declare_var(Parser* p, Symbol* sym, int isref) +{ + if (!sym->global) + { + printf(" "); + } + make_var(p, sym, isref); +} + + static int declare_temp(Parser* p, Type* type, int isref) { char name[32]; @@ -88,16 +129,44 @@ static int declare_temp(Parser* p, Type* type, int isref) .name = name, .type = type, }; - declare_var(p, &sym, isref); + if (type->form == FORM_RECORD) + { + printf(" char* %s", name); + } + else + { + declare_var(p, &sym, isref); + } p->curr_reg++; return reg; } +static char* temp(Item* a) +{ + char name[32]; + if (a->mode == ITEM_INDEX) + { + snprintf(name, sizeof(name), "(*_T%d)", a->reg); + } + else if (a->mode == ITEM_FIELD) + { + snprintf(name, sizeof(name), "*((%s)_T%d)", typetoptr(a->type), a->reg); + } + else + { + snprintf(name, sizeof(name), "(_T%d)", a->reg); + } + return strdup(name); +} + static void load_var(Parser* p, Item* item) { if (!item->reg) { - int isref = (item->type->form == FORM_ARRAY); + int isref = ( + (item->type->form == FORM_ARRAY) + || (item->type->form == FORM_RECORD) + ); switch (item->mode) { case ITEM_CONST: @@ -108,13 +177,26 @@ static void load_var(Parser* p, Item* item) case ITEM_VAR: item->reg = declare_temp(p, item->type, isref); - printf(" = %c%s;\n", (isref ? '&' : ' '), item->imm.s); + if (item->type->form == FORM_RECORD) + { + printf(" = (char*)&%s[0];\n", item->imm.s); + } + else + { + printf(" = %c%s;\n", (isref ? '&' : ' '), item->imm.s); + } break; case ITEM_MVAR: item->reg = declare_temp(p, item->type, isref); - printf(" = %c%s_%s;\n", - (isref ? '&' : ' '), p->name, item->imm.s); + if (item->type->form == FORM_RECORD) + { + printf(" = &%s_%s[0];\n", p->name, item->imm.s); + } + else + { + printf(" = %c%s_%s;\n", (isref ? '&' : ' '), p->name, item->imm.s); + } break; default: @@ -123,15 +205,6 @@ static void load_var(Parser* p, Item* item) } } -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) @@ -214,7 +287,7 @@ void codegen_startproc(Parser* p, Symbol* proc) proc->name); for (Symbol* arg = proc->desc; arg; arg = arg->next) { - printf("%s %s", TypeNames[arg->type->form], arg->name); + make_var(p, arg, false); if (arg->next) { printf(", "); @@ -280,6 +353,12 @@ void codegen_store(Parser* p, Item* a, Item* b) load_var(p, b); printf(" %s = %s;\n", temp(a), temp(b)); } + else if (a->mode == ITEM_FIELD) + { + load_var(p, b); +// printf(" *((%s)%s) = %s;\n", typetoptr(a->type), temp(a), temp(b)); + printf(" %s = %s;\n", temp(a), temp(b)); + } else { assert(!"bad store op"); @@ -377,3 +456,33 @@ void codegen_index(Parser* p, Item* array, Item* index) printf(" = &%s[%s];\n", temp(array), temp(index)); array->reg = dest_reg; } + +Field* get_field(Parser* p, Type* type, char* name) +{ + Field* curr = type->fields; + while (curr) + { + if (curr->name && !strcmp(curr->name, name)) + { + break; + } + curr = curr->next; + } + if (!curr) + { + error(p, "record has no such field '%s'\n", name); + } + return curr; +} + +void codegen_field(Parser* p, Item* record, char* name) +{ + load_var(p, record); + Field* f = get_field(p, record->type, name); + record->mode = ITEM_FIELD; + record->type = f->type; + printf(" char* _T%d", p->curr_reg); + p->curr_reg++; + printf(" = _T%d + %ld;\n", record->reg, f->offset); + record->reg = p->curr_reg-1; +} diff --git a/cerise/backend/test/codegen.c b/cerise/backend/test/codegen.c index 3502455..91ebd32 100644 --- a/cerise/backend/test/codegen.c +++ b/cerise/backend/test/codegen.c @@ -125,3 +125,9 @@ void codegen_index(Parser* p, Item* array, Item* index) { (void)p, (void)array, (void)index; } + +void codegen_field(Parser* p, Item* record, char* name) +{ + (void)p, (void)record, (void)name; +} + diff --git a/cerise/backend/x86_64/codegen.c b/cerise/backend/x86_64/codegen.c index db4efab..85023cb 100644 --- a/cerise/backend/x86_64/codegen.c +++ b/cerise/backend/x86_64/codegen.c @@ -355,3 +355,8 @@ void codegen_index(Parser* p, Item* array, Item* index) { (void)p, (void)array, (void)index; } + +void codegen_field(Parser* p, Item* record, char* name) +{ + (void)p, (void)record, (void)name; +} diff --git a/cerise/inc/cerise.h b/cerise/inc/cerise.h index 25d4f67..59c1ec6 100644 --- a/cerise/inc/cerise.h +++ b/cerise/inc/cerise.h @@ -128,7 +128,7 @@ typedef struct Module { typedef struct Item { struct Item* next; enum { - ITEM_CONST, ITEM_VAR, ITEM_MVAR, ITEM_REG, ITEM_INDEX + ITEM_CONST, ITEM_VAR, ITEM_MVAR, ITEM_REG, ITEM_INDEX, ITEM_FIELD } mode; Symbol* sym; Type* type; @@ -222,6 +222,7 @@ void codegen_call(Parser* p, Item* item, Item* args); void codegen_setarg(Parser* p, Item* item, bool firstarg); void codegen_return(Parser* p, Item* item); void codegen_index(Parser* p, Item* array, Item* index); +void codegen_field(Parser* p, Item* record, char* name); /* diff --git a/cerise/src/grammar.c b/cerise/src/grammar.c index ec56a0f..595a809 100644 --- a/cerise/src/grammar.c +++ b/cerise/src/grammar.c @@ -169,9 +169,20 @@ RULE(designator) { switch ((int)peek(p)->type) { - // case '.': - // expect(p, IDENT); - // break; + case '.': + { + expect(p, '.'); + char* name = expect_text(p, IDENT); + if (item->type->form == FORM_RECORD) + { + codegen_field(p, item, name); + } + else + { + error(p, "attempting to access field of non-array object"); + } + break; + } case '[': { diff --git a/cerise/tests/Module.m b/cerise/tests/Module.m index 52f0504..64f8e5c 100644 --- a/cerise/tests/Module.m +++ b/cerise/tests/Module.m @@ -15,6 +15,9 @@ type TypeD = record x,y : Int label : array 10 of Real + dim : record + w,h : Int + end end var @@ -23,8 +26,9 @@ var c : Int d : Real e : array 5 of array 10 of Int + f : TypeD -procedure Foo*(e : Int, z : Int) : Int +procedure Foo*(e : Int, z : Int, q1 : TypeD, q2 : array 5 of Int) : Int const FOO = 2 type foo = Int var @@ -108,4 +112,6 @@ begin # e[b] = 1; # e[1][2] = 1; # c = e[1][c]; + c = f.dim.w; + f.dim.h = 0; end -- 2.49.0