From: Michael D. Lowis Date: Sun, 2 Oct 2022 00:36:45 +0000 (-0400) Subject: record field access is working now X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=184856773ff1fd90717db5e01edf69cdd43cb904;p=proto%2Fobnc.git record field access is working now --- diff --git a/cerise/backend/ssa/codegen.c b/cerise/backend/ssa/codegen.c index e8cc367..6fa2491 100644 --- a/cerise/backend/ssa/codegen.c +++ b/cerise/backend/ssa/codegen.c @@ -182,6 +182,8 @@ static void topsort(Bitset* set, SsaBlock** sorted, SsaBlock* block) static void print_ident(Parser* p, SsaVar* var) { Symbol* s = symbol_getbyid(p, var->symid); + assert(s); + assert(s->name); char* name = (s->name[0] == '$' ? "" : s->name); if ((s->global || s->class == SYM_PROC) && (s->class != SYM_TYPE)) { @@ -325,6 +327,30 @@ void print_op(Parser* p, SsaNode* expr) print_oparg(p, expr->right); puts(""); } + else if (expr->code == '.') + { + printf(" "); + print_ident(p, &(SSA_VAR(expr))); + printf(" = getelementptr "); + emit_type(SSA_LTYPE(expr)); + printf(", "); + emit_type(SSA_LTYPE(expr)); + printf("* "); + print_ident(p, &(SSA_LVAR(expr))); + printf(", i64 0"); + int num = 0; + char* fname = ssa_asstring(expr->right); + struct Field* field = SSA_LTYPE(expr)->fields; + for (; field; field = field->next, num++) + { + if (!strcmp(fname, field->name)) + { + break; + } + } + printf(", i32 %d", num); + puts(""); + } else { assert(!"not implemented"); diff --git a/cerise/inc/cerise.h b/cerise/inc/cerise.h index 797146d..62ac170 100644 --- a/cerise/inc/cerise.h +++ b/cerise/inc/cerise.h @@ -125,6 +125,7 @@ typedef union { SsaVar var; SsaConst val; struct SsaBlock* block; + char* str; } SsaValue; //typedef struct SsaNode { @@ -300,6 +301,7 @@ bool bitset_has(Bitset* set, size_t val); bool ssa_asbool(SsaNode* node); long long ssa_asint(SsaNode* node); double ssa_asreal(SsaNode* node); +char* ssa_asstring(SsaNode* node); void ssa_join(Parser* p); void ssa_reset_vars(Parser* p); @@ -308,6 +310,7 @@ SsaNode* ssa_ident(Parser* p, long long index); SsaNode* ssa_bool(Parser* p, bool val); SsaNode* ssa_int(Parser* p, long long val); SsaNode* ssa_real(Parser* p, double val); +SsaNode* ssa_string(Parser* p, char* val); SsaNode* ssa_op(Parser* p, int op, SsaNode* left, SsaNode* right); SsaNode* ssa_store(Parser* p, SsaNode* dest, SsaNode* value); diff --git a/cerise/src/ssa.c b/cerise/src/ssa.c index a5a2980..2e3ef55 100644 --- a/cerise/src/ssa.c +++ b/cerise/src/ssa.c @@ -26,6 +26,12 @@ double ssa_asreal(SsaNode* node) return (SSA_VAL(node).f); } +char* ssa_asstring(SsaNode* node) +{ + assert(node->code == STRING); + return (SSA_VAL(node).s); +} + /* * store backup values for var versions, restore at the end of block * popping a join node processes phis as stores propagating phis to outer join nodes @@ -172,6 +178,15 @@ SsaNode* ssa_real(Parser* p, double val) return node; } +SsaNode* ssa_string(Parser* p, char* val) +{ + (void)p; + SsaNode* node = ssa_node(STRING, MODE_CONST); + node->type = &StringType; + SSA_VAL(node).s = val; + return node; +} + SsaNode* ssa_op(Parser* p, int op, SsaNode* left, SsaNode* right) { return (right != NULL) @@ -182,7 +197,7 @@ SsaNode* ssa_op(Parser* p, int op, SsaNode* left, SsaNode* right) SsaNode* ssa_store(Parser* p, SsaNode* dest, SsaNode* value) { value = load(p, value); - if (dest->mode == MODE_MEMORY && dest->code == '[') + if (dest->mode == MODE_MEMORY && (dest->code == '[' || dest->code == '.')) { dest = load(p, dest); } @@ -204,27 +219,36 @@ SsaNode* ssa_store(Parser* p, SsaNode* dest, SsaNode* value) SsaNode* ssa_fieldref(Parser* p, SsaNode* record, char* fname) { -#if 1 - (void)p, (void)record, (void)fname; - assert(!"record field references unimplemented"); - return NULL; -#else - if (record->mode == MODE_MEMORY && record->code == '[') + if (record->mode == MODE_MEMORY && (record->code == '[' || record->code == '.')) { record = load(p, record); } - index = load(p, index); - SsaNode* node = ssa_node('[', MODE_MEMORY); - node->type = array->type->base; - node->left = array; - node->right = index; + + /* make sure the referenced field exists */ + struct Field* field = record->type->fields; + for (; field; field = field->next) + { + if (!strcmp(fname, field->name)) + { + break; + } + } + if (!field) + { + error(p, "record has no field named '%s'", fname); + } + + /* now create and return the node */ + SsaNode* node = ssa_node('.', MODE_MEMORY); + node->type = field->type; + node->left = record; + node->right = ssa_string(p, fname); return node; -#endif } SsaNode* ssa_index(Parser* p, SsaNode* array, SsaNode* index) { - if (array->mode == MODE_MEMORY && array->code == '[') + if (array->mode == MODE_MEMORY && (array->code == '[' || array->code == '.')) { array = load(p, array); } @@ -530,7 +554,7 @@ static SsaNode* load(Parser* p, SsaNode* node) static SsaNode* loadmem(Parser* p, SsaNode* node) { node = load(p, node); - if (node->mode == MODE_MEMORY && node->code == '[') + if (node->mode == MODE_MEMORY && (node->code == '[' || node->code == '.')) { SsaNode* load_op = ssa_node(LOAD, MODE_MEMORY); load_op->left = node; diff --git a/cerise/tests/Module.m b/cerise/tests/Module.m index 0c8f260..3cd964f 100644 --- a/cerise/tests/Module.m +++ b/cerise/tests/Module.m @@ -172,12 +172,13 @@ end procedure TestRecordAccess() begin -# vRec2.a = vRec2.a + vRec2.a; + vRec2.a = vRec2.a + vRec2.a; +# vInt = vRec2.a; # TODO: This is broken! end procedure TestNestedRecordAccess() begin -# vRec2.a.b = vRec2.a.b + vRec2.a.b; + vRec1.b.c = vRec1.b.c + vRec1.b.c; # TODO: This is broken! end #begin