Aria

A low-level systems programming language
git clone git://git.m21c.me/Aria.git
Log | Files | Refs | LICENSE

commit f98725c44ba9e0107206fe692d57cc8d6ca4f454
parent 6ed7b3405e9d0358f51a4092496c3c08678bd627
Author: m21c  <ho*******@gmail.com>
Date:   Thu,  2 Feb 2023 05:05:15 +0100

worked on data-flow analysis

Diffstat:
Mcompiler.c | 521+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 521 insertions(+), 0 deletions(-)

diff --git a/compiler.c b/compiler.c @@ -46,6 +46,15 @@ struct Env Env; +typedef +struct Gist Gist; + +typedef +struct Conduct Conduct; + +typedef +struct Block Block; + /* SECTION: - node kind table - */ @@ -395,6 +404,18 @@ enum Qualifier { } Qualifier; +typedef +enum BlockKind { + BTOPLEVEL = 0, + BFUNCTION = 1, + BSCOPE = 2, + BIF = 3, + BLOOP = 4, + BWHILELOOP = 5, + BLOOPUNTIL = 6, + BFORLOOP = 7, + BELSE = 8 +} BlockKind; @@ -522,6 +543,61 @@ struct Source { } Source; +struct Gist { + Decl *decl; + Conduct *parent; + + bool init; + Node *where; + + /* for other declarations */ + Gist *prev, *next; +}; + +struct Block { + BlockKind kind; + + Env *env; + + /* Conduct-Sequence list*/ + Conduct *head, *tail, *parent; + + /* Neighbooring Blocks */ + Block *prev, *next; +}; + +struct Conduct { + ConductKind kind; + uint id; + + Node *label, *branch; + Node *first, *last; + + bool doesbreak; + bool doescontinue; + bool doesreturn; + bool doesjump; + + struct ConductGists { + Gist *head, *tail; + } gists; + + struct ConductBranches { + /* Branch-relation from child to parents */ + Conduct *head, *tail; + + /* Branch-parent list */ + Conduct *next, *prev; + } branches; + + /* Block-stack */ + Block *head, *tail, *parent; + + /* Conduct-sequence list */ + Conduct *next, *prev; +}; + + /* SECTION: - global-vars - */ @@ -3889,6 +3965,445 @@ foldexpr(Env *env, Node *expr) +/* SECTION: - data-flow analysis - */ + +/* +In order to do DFA, we divide the code of a scope into sections. +For each section there will be a DF-Conduct associated with it. + +*/ + +Block blockbuf[1024*8]; +int blocktop; + +Conduct conductbuf[1024*8]; +int conducttop; + +Gist gistbuf[1024*8]; +int gisttop; + +static Block * +makeblock(BlockKind kind, Env *env) +{ + Block *block; + + assert(blocktop < lengthof(blockbuf)); + + block = blockbuf + blocktop++; + + memset(block, 0, sizeof(*block)); + + block->kind = kind; + block->env = env; + + return block; +} + +static Conduct * +makeconduct(ConductKind kind, Node *label) +{ + Conduct *conduct; + + assert(conducttop < lengthof(conductbuf)); + + conduct = conductbuf + conducttop++; + + memset(conduct, 0, sizeof(*conduct)); + + conduct->kind = kind; + conduct->label = label; + + return conduct; +} + +static void +transfergists(Conduct *source, Conduct *dest); + +static void +appendconduct(Block *parent, ConductKind kind, Node *label) +{ + Conduct *conduct = makeconduct(kind, label); + + if (!parent) + return; + + conduct->parent = parent; + + listappend(parent, conduct); + + if (conduct->prev) + transfergists(conduct->prev, conduct); +} + +static void +appendblock(Conduct *parent, BlockKind kind, Env *env) +{ + Block *block = makeblock(kind, env); + + appendconduct(block, CSCOPE, NULL); + + if (!parent) + return; + + block->parent = parent; + + listappend(parent, block); + + transfergists(parent, block->tail); +} + +static Gist * +makegist(Decl *decl, Node *where, bool init) +{ + Gist *gist; + assert(gisttop < lengthof(gistbuf)); + + gist = gistbuf + gisttop++; + + memset(gist, 0, sizeof(*gist)); + + gist->decl = decl; + gist->where = where; + gist->init = init; + + return gist; +} + +static void +appendgist(Conduct *conduct, Gist *info) +{ + info->parent = conduct; + + listappendex(conduct, info, gists.head, gists.tail, prev, next); +} + +static void +transfergists(Conduct *source, Conduct *dest) +{ + Gist *info; + + for (info = source->gists.head; info; info = info->next) { + Gist *copy = makegist(NULL, NULL, false); + + *copy = *info; + + appendgist(dest, copy); + } +} + +static Gist * +getgist(Conduct *conduct, Decl *decl) +{ + Gist *probe; + assert(conduct); + + for (probe = conduct->gists.head; probe; probe = probe->next) { + if (probe->decl == decl) + return probe; + } + + return NULL; +} + +static void +gistread(Conduct *conduct, Node *node) +{ + const char *name; + Decl *decl; + Gist *info; + + if (!node || (node->kind != ADECLREF && node->kind != ADECL)) + return; + + decl = node->u.declref; + + /* NOTE(m21c): additional checks require that this moves + * somewhere else. */ + if ( decl->kind == DPARAM || + (decl->kind == DVAR && + decl->parentenv && + decl->parentenv->kind == STOPLEVEL)) + return; + + name = getstring(idents, decl->key); + info = getgist(conduct, decl); + + if (info) { + Node *where = info->where; + + if (info->init) + return; + + assert(where); + error(&node->loc, "use of un-initialized '%s'.", name); + /* TODO(m21c): change to notice or similiar, + * instead of warn */ + warn(&where->loc, "last use of '%s' was here.", name); + } else { + error(&node->loc, "use of un-initialized '%s'.", name); + } +} + +static void +gistwrite(Conduct *conduct, Node *node, bool init) +{ + Decl *decl; + Gist *info; + + if (!node || (node->kind != ADECLREF && node->kind != ADECL)) + return; + + decl = node->u.declref; + + info = getgist(conduct, decl); + if (!info) { + info = makegist(decl, node, init); + appendgist(conduct, info); + return; + } + + info->init = init; + info->where = node; +} + +static void +fetchblocks(Block *block, Node *expr); + +static void +fetchscoped(Conduct *conduct, Node *expr, BlockKind kind) +{ + if (expr && expr->kind == ASCOPE) { + appendblock(conduct, kind, expr->u.env); + fetchblocks(conduct->tail, expr->lhs); + + } else if (expr) { + assert(conduct->parent); + assert(conduct->parent->env); + + appendblock(conduct, kind, conduct->parent->env); + fetchblocks(conduct->tail, expr); + } +} + +static void +fetchblocks(Block *block, Node *expr) +{ + Node *lhs, *rhs; + + assert(expr); + assert(block); + assert(block->tail); + + lhs = expr->lhs; + rhs = expr->rhs; + + switch (expr->kind) { + /* unary read */ + case ODEREF: + case OPLUS: case OMINUS: + case OBNOT: + case OLNOT: + case OCAST: + fetchblocks(block, lhs); + gistread(block->tail, lhs); + return; + + /* unary read/write */ + case OINC: case ODEC: + case OSUFINC: case OSUFDEC: + fetchblocks(block, lhs); + gistread(block->tail, lhs); + gistwrite(block->tail, lhs, true); + return; + + /* binary read */ + case OMUL: case ODIV: case OMOD: + case OADD: case OSUB: + case OBAND: case OBOR: case OXOR: + case OLSH: case ORSH: case OARSH: + case OEQU: case ONEQ: + case OLET: case OLEQ: + case OGRT: case OGEQ: + case OLAND: case OLOR: + fetchblocks(block, lhs); + gistread(block->tail, lhs); + + fetchblocks(block, rhs); + gistread(block->tail, rhs); + return; + + + /* binary write */ + case OASS: + fetchblocks(block, rhs); + gistread(block->tail, rhs); + + fetchblocks(block, lhs); + gistwrite(block->tail, lhs, true); + return; + + /* binary read/write */ + case OMULA: case ODIVA: case OMODA: + case OADDA: case OSUBA: + case OLSHA: case ORSHA: case OARSHA: + case OANDA: + case OORA: case OXORA: + fetchblocks(block, rhs); + gistread(block->tail, rhs); + + fetchblocks(block, lhs); + gistread(block->tail, lhs); + gistwrite(block->tail, lhs, true); + return; + + case ASTMT: + advancestmt: + assert(lhs); + + fetchblocks(block, lhs); + + if (expr->rhs) { + assert(expr->rhs->kind == ASTMT); + expr = expr->rhs, lhs = expr->lhs; + goto advancestmt; + } + return; + + case ADECL: + assert(expr->u.declref); + lhs = expr->u.declref->u.content; + + if (expr->u.declref->kind == DFUNCTION) { + fetchscoped(block->tail, lhs, BFUNCTION); + appendconduct(block, CSCOPE, NULL); + } else if (lhs) { + appendblock(block->tail, BSCOPE, expr->u.env); + fetchblocks(block->tail->tail, lhs); + appendconduct(block, CSCOPE, NULL); + } + + gistwrite(block->tail, expr, !!lhs); + return; + + case ASCOPE: + assert(lhs); + + appendblock(block->tail, BSCOPE, expr->u.env); + fetchblocks(block->tail->tail, lhs); + appendconduct(block, CSCOPE, NULL); + return; + + case KIF: + assert(lhs); + assert(expr->u.payload); + + fetchscoped(block->tail, lhs, BIF); + if (rhs) + fetchscoped(block->tail, rhs, BELSE); + + appendconduct(block, CSCOPE, NULL); + return; + + case KDO: + return; + + case KLOOP: + return; + + case ALOOPUNTIL: + return; + + case KBREAK: + block->tail->doesbreak = true; + goto joinctrltransfer; + + case KCONTINUE: + block->tail->doescontinue = true; + goto joinctrltransfer; + + case KRETURN: + block->tail->doesreturn = true; + goto joinctrltransfer; + + case KGOTO: + block->tail->doesjump = true; + joinctrltransfer: + appendconduct(block, CUNREACH, NULL); + return; + + default: + case OADDR: + return; + } +} + +static void +debugprintconduct(Conduct *conduct, int indent); + +static void +debugprintblock(Block *block, int indent) +{ + Block *curr; + assert(block); + + for (curr = block; curr; curr = curr->next) { + int i; + + for (i = 0; i < indent; ++i) { + printf("\t"); + } + + switch (curr->kind) { + case BTOPLEVEL: printf("\x1b[31mblock<toplevel>\x1b[0m\n"); break; + case BFUNCTION: printf("\x1b[31mblock<function>\x1b[0m\n"); break; + case BSCOPE: printf("\x1b[31mblock<scope>\x1b[0m\n"); break; + case BIF: printf("\x1b[31mblock<if>\x1b[0m\n"); break; + case BLOOP: printf("\x1b[31mblock<loop>\x1b[0m\n"); break; + case BWHILELOOP: printf("\x1b[31mblock<while-loop>\x1b[0m\n"); break; + case BLOOPUNTIL: printf("\x1b[31mblock<loop-until>\x1b[0m\n"); break; + case BFORLOOP: printf("\x1b[31mblock<for-loop>\x1b[0m\n"); break; + case BELSE: printf("\x1b[31mblock<else>\x1b[0m\n"); break; + } + + if (curr->head) + debugprintconduct(curr->head, indent); + } +} + +static void +debugprintconduct(Conduct *conduct, int indent) +{ + Conduct *curr; + assert(conduct); + + for (curr = conduct; curr; curr = curr->next) { + int i; + + for (i = 0; i < indent; ++i) { + printf("\t"); + } + + switch (curr->kind) { + case CUNREACH: printf("\x1b[34mconduct<unreach>\x1b[0m\n"); break; + case CSCOPE: printf("\x1b[34mconduct<scope>\x1b[0m\n"); break; + case CLABEL: printf("\x1b[34mconduct<label>\x1b[0m\n"); break; + } + + if (curr->head) + debugprintblock(curr->head, indent + 1); + } +} + +static void +dataflow(Block *block, Node *expr) +{ + assert(expr); + + fetchblocks(block, expr); + + debugprintblock(block, 0); +} + /* SECTION: - print ast - */ @@ -4850,6 +5365,7 @@ int main(int argc, char **argv) { Env *p; + Block *block; Source *source = &testsource; source->tabwidth = 8; @@ -4871,6 +5387,8 @@ main(int argc, char **argv) } pushenv(source, STOPLEVEL); + block = makeblock(BTOPLEVEL, source->currenv); + appendconduct(block, CSCOPE, NULL); while (getkind(source) != 0) { /* printf("token:%i:%i: %c '%.*s'\n", lastline, lastcol + 1, tok.u.id, currcol - lastcol, line + lastcol);*/ @@ -4888,6 +5406,7 @@ main(int argc, char **argv) { ast = typecheck(source->currenv, ast); ast = foldexpr(source->currenv, ast); + dataflow(block, ast); } if (source->filein == stdin) { @@ -4952,6 +5471,7 @@ main(int argc, char **argv) if (p->stmts) { p->stmts = typecheck(source->currenv, p->stmts); p->stmts = foldexpr(source->currenv, p->stmts); + dataflow(block, p->stmts); /* debug prints: */ highlight(stdout, HLINFO); @@ -4968,6 +5488,7 @@ main(int argc, char **argv) } } + /* dfpopconduct(); */ popenv(source); highlight(stdout, HLINFO);