scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit b1235747c1c0b59be05f56a068a2d0f912b10227
parent 9b361f53cda590cb1dc5645301f600dac17d1c5d
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Fri, 20 Mar 2015 14:49:44 -0400

Simplify add() function in cc2

These function was a spaguetti code with switch. This new
version is a bit better and use some ideas taken again
from ken_cc.

Diffstat:
Mcc2/cc2.h | 2+-
Mcc2/cgen.c | 141++++++++++++++++++++++++++++++++++++-------------------------------------------
2 files changed, 66 insertions(+), 77 deletions(-)

diff --git a/cc2/cc2.h b/cc2/cc2.h @@ -8,7 +8,6 @@ #define MEM 'T' #define PAR 'P' #define CONST '#' -#define PUSHED 'S' #define INDEX 'I' #define LABEL 'L' #define OADD '+' @@ -58,6 +57,7 @@ struct symbol { bool public : 1; bool extrn : 1; bool dirty : 1; + bool index : 1; union { /* TODO: Admit inmediate of other type */ TINT imm; diff --git a/cc2/cgen.c b/cc2/cgen.c @@ -107,31 +107,35 @@ allocreg(Node *np) abort(); } +static void moveto(Node *np, uint8_t reg); + static void spill(uint8_t reg) { Node *np, *r; Symbol *sym; - uint8_t p, h, l; + uint8_t p, h, l, new; if ((np = reguse[reg]) == NULL) return; - if ((sym = np->sym) == NULL) - goto freereg; - if (!sym->dirty) - goto freereg; - + sym = np->sym; r = &regs[reg]; + switch (np->type.size) { case 1: - code(LDL, np, r); + if (sym) { + code(LDL, np, r); + np->op = sym->kind; + sym->dirty = 0; + } else { + new = allocreg(np); + moveto(np, new); + } break; default: abort(); } - sym->dirty = 0; -freereg: reguse[reg] = NULL; p = pair[reg]; l = lower[p]; @@ -159,6 +163,7 @@ moveto(Node *np, uint8_t reg) switch (np->type.size) { case 1: switch (op) { + case MEM: case AUTO: code(LDL, r, np); break; @@ -196,23 +201,15 @@ moveto(Node *np, uint8_t reg) } static void -move(Node *np) -{ - moveto(np, allocreg(np)); -} - -static void accum(Node *np) { Symbol *sym; switch (np->type.size) { case 1: - spill(A); moveto(np, A); break; case 2: - spill(HL); moveto(np, HL); break; case 4: @@ -225,6 +222,7 @@ static void index(Node *np) { Node *u = reguse[HL]; + Symbol *sym; if (u && u->sym) { if (u->op == INDEX && np->sym == u->sym) { @@ -235,11 +233,39 @@ index(Node *np) } } code(LDI, &regs[HL], np); + if (sym = np->sym) + sym->index = 1; np->op = INDEX; reguse[HL] = reguse[H] = reguse[L] = np; } static void +move(Node *np, Node *parent) +{ + assert(np->type.size == 1); + switch (parent->op) { + case OADD: + case OSUB: + switch (np->op) { + case PAR: + case AUTO: + case CONST: + case INDEX: + case REG: + return; + case MEM: + index(np); + break; + default: + abort(); + } + break; + default: + abort(); + } +} + +static void conmute(Node *np) { Node *p, *q; @@ -253,72 +279,32 @@ conmute(Node *np) static void add(Node *np) { - Node *lp = np->left, *rp = np->right; - uint8_t i; + Node *lp = np->left, *rp = np->right, *a; - if (rp->op == REG || lp->op == CONST) { - conmute(np); - lp = np->left; - rp = np->right; - } switch (np->type.size) { case 1: - switch (lp->op) { - case PAR: - case AUTO: - switch (rp->op) { - case MEM: - index(rp); - case PAR: - case AUTO: - case CONST: - accum(lp); - break; - default: - abort(); - } - break; - case MEM: - if (reguse[A]) { - switch (rp->op) { - case PAR: - case AUTO: - case CONST: - break; - case MEM: - index(rp); - goto add_A; - default: - abort(); - } - } - accum(lp); - break; - case REG: - if (lp->reg != A) - moveto(lp, A); - switch (rp->op) { - case REG: - case AUTO: - case PAR: - case CONST: - case MEM: - break; - default: - abort(); - } - break; - default: - abort(); + a = reguse[A]; + if (a == lp) + goto add1; + if (a == rp) + goto conmute1; + if (lp->op == CONST) { + accum(rp); + goto conmute1; } - add_A: + accum(lp); + goto add1; + conmute1: + conmute(np); + lp = np->left, rp = np->right; + add1: + move(rp, np); code((np->op == OADD) ? ADD : SUB, lp, rp); np->op = REG; np->reg = A; + reguse[A] = np; break; - case 2: - case 4: - case 8: + default: abort(); } } @@ -330,15 +316,18 @@ assign(Node *np) Symbol *sym = lp->sym; assert(rp->op == REG); + /* TODO: what happens with the previous register? */ switch (np->type.size) { case 1: switch (lp->op) { case MEM: + if (sym && sym->index) + lp->op = INDEX; + case INDEX: case AUTO: code(LDL, lp, rp); break; case REG: - /* TODO: what happens with the previous register? */ code(MOV, lp, rp); break; default: