ref: 36a3a5fa99dc4887ca46c7807436ad44da19422f
dir: /8/reduce.c/
#include <stdlib.h> #include <stdio.h> #include <stdint.h> #include <ctype.h> #include <string.h> #include <assert.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include "parse.h" #include "gen.h" /* takes a list of nodes, and reduces it (and it's subnodes) to a list * following these constraints: * - All nodes are expression nodes * - Nodes with side effects are root nodes * - All nodes operate on machine-primitive types and tuples */ typedef struct Simp Simp; struct Simp { Node **blk; size_t nblk; Node *endlbl; Node *retval; }; Node *simp(Simp *s, Node *n); void append(Simp *s, Node *n) { lappend(&s->blk, &s->nblk, n); } int isimpure(Node *n) { return 0; } Node *genlbl(void) { char buf[128]; static int nextlbl; snprintf(buf, 128, ".L%d", nextlbl++); return mklbl(-1, buf); } Node *temp(Node *e) { char buf[128]; static int nexttmp; Node *n; Node *t; Sym *s; assert(e->type == Nexpr); snprintf(buf, 128, ".t%d", nexttmp++); n = mkname(-1, buf); s = mksym(-1, n, e->expr.type); t = mkdecl(-1, s); return mkexpr(-1, Ovar, t, NULL); } void cjmp(Simp *s, Node *cond, Node *iftrue, Node *iffalse) { Node *jmp; jmp = mkexpr(-1, Ocjmp, cond, iftrue, iffalse, NULL); append(s, jmp); } void jmp(Simp *s, Node *lbl) { append(s, mkexpr(-1, Ojmp, lbl, NULL)); } Node *store(Node *t, Node *n) { return mkexpr(-1, Oasn, t, n, NULL); } Node *storetmp(Node *n) { return store(temp(n), n); } /* if foo; bar; else baz;; * => cjmp (foo) :bar :baz */ void simpif(Simp *s, Node *n) { Node *l1, *l2; Node *c; l1 = genlbl(); l2 = genlbl(); c = simp(s, n->ifstmt.cond); cjmp(s, c, l1, l2); simp(s, l1); simp(s, n->ifstmt.iftrue); simp(s, l2); simp(s, n->ifstmt.iffalse); } /* init; while cond; body;; * => init * jmp :cond * :body * ...body... * :cond * ...cond... * cjmp (cond) :body :end * :end */ void simploop(Simp *s, Node *n) { Node *lbody; Node *lend; Node *lcond; Node *c; lbody = genlbl(); lcond = genlbl(); lend = genlbl(); simp(s, n->loopstmt.init); jmp(s, lcond); simp(s, lbody); simp(s, n->loopstmt.body); simp(s, n->loopstmt.step); simp(s, lcond); c = simp(s, n->loopstmt.cond); cjmp(s, c, lbody, lend); simp(s, lend); } void simpblk(Simp *s, Node *n) { int i; Node *e; for (i = 0; i < n->block.nstmts; i++) { e = simp(s, n->block.stmts[i]); append(s, e); } } Node *simpexpr(Simp *s, Node *n) { Node *r, *t; int i; switch (exprop(n)) { case Ovar: break; case Oret: if (n->expr.args[0]) { t = storetmp(simp(s, n->expr.args[0])); append(s, t); } jmp(s, s->endlbl); break; default: if (isimpure(n)) { r = simp(s, n); t = storetmp(r); append(s, t); return t; } else { for (i = 0; i < n->expr.nargs; i++) n->expr.args[i] = simp(s, n->expr.args[i]); } } return n; } Node *simp(Simp *s, Node *n) { Node *r; r = NULL; switch (n->type) { case Nblock: simpblk(s, n); break; case Nifstmt: simpif(s, n); break; case Nloopstmt: simploop(s, n); break; case Nexpr: r = simpexpr(s, n); break; case Nlit: r = n; break; case Ndecl: //declare(s, n); break; case Nlbl: append(s, n); break; default: die("Bad node passsed to simp()"); break; } return r; } Node **reduce(Node *n, int *ret_nn) { Simp s = {0,}; s.nblk = 0; s.endlbl = genlbl(); s.retval = NULL; switch (n->type) { /* these should never be inside functions */ case Nnone: case Nfile: die("Bad node type in func"); break; case Nfunc: die("FIXME: generate thunks"); break; /* no code generated */ case Nuse: break; /* complex nodes */ case Nblock: simp(&s, n); break; case Nifstmt: case Nloopstmt: case Nexpr: case Nlit: case Nname: case Ndecl: case Nlbl: break; } append(&s, s.endlbl); *ret_nn = s.nblk; return s.blk; }