ref: 827b4cdaa90cabaa1ee149a79ceb4cf7c7813f47
parent: 9a2913311bd77d7075a327854a725d03eff554a2
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Wed Jan 20 15:11:09 EST 2016
Move cc2 to cc2.old We are going to begin with the new backend, and it is better to begin from scratch, but with an eye in the older.
--- /dev/null
+++ b/cc2.old/Makefile
@@ -1,0 +1,23 @@
+.POSIX:
+
+include ../config.mk
+
+OBJS = main.o parser.o cgen.o code.o optm.o peep.o
+
+all: cc2
+
+
+$(OBJS): ../inc/cc.h ../inc/sizes.h cc2.h
+main.o: error.h
+
+error.h: cc2.h
+ rm -f $@; trap 'rm -f $$$$.h' EXIT INT QUIT
+ awk -f generror cc2.h > $$$$.h && mv $$$$.h $@
+
+cc2: $(OBJS) ../lib/libcc.a
+ $(CC) $(LDFLAGS) $(OBJS) ../lib/libcc.a -o $@
+
+clean:
+ rm -f $(OBJS)
+ rm -f cc2 error.h
+
--- /dev/null
+++ b/cc2.old/cast.patch
@@ -1,0 +1,61 @@
+diff --git a/cc2/cgen.c b/cc2/cgen.c
+index be4ff41..8839505 100644
+--- a/cc2/cgen.c
++++ b/cc2/cgen.c
+@@ -449,16 +449,50 @@ cast(Node *np)
+ {
+ Node *lp = np->left;
+ uint8_t reg;
++ int8_t delta;
+
+- if (lp->type.size != np->type.size)
++ swtich (lp->type.size) {
++ case 1:
++ switch (np->type.size) {
++ case 1:
++ break;
++ case 2:
++ if (lp->op != REG)
++ move(lp, np);
++ np->reg = reg = lp->reg;
++ if (lp->sign && np->sign) {
++ code(BIT, lp, imm(7));
++ code(JRZ, .., ..);
++ code(LDI, regs[upper[reg]], imm(-1));
++ code(JR, ..., ...);
++ }
++ reguse[pair[reg]] = reguse[reg] = np;
++ code(LDI, regs[lower[reg]], imm(0));
++ break;
++ default:
++ abort();
++ }
++ break;
++ case 2:
++ switch (np->type.size) {
++ case 1:
++ if (lp->op == REG) {
++ reguse[upper[reg]] = NULL;
++ reg = lower[reg];
++ np->reg = reg;
++ reguse[pair[reg]] = reguse[reg] = np;
++ }
++ break;
++ case 2:
++ break;
++ default:
++ abort();
++ }
++ default:
+ abort();
++ }
+ lp->used = 1;
+ np->sym = lp->sym;
+- if ((np->op = lp->op) == REG) {
+- reg = lp->reg;
+- np->reg = reg;
+- reguse[pair[reg]] = reguse[reg] = np;
+- }
+ }
+
+ static void (*opnodes[])(Node *) = {
--- /dev/null
+++ b/cc2.old/cc2.h
@@ -1,0 +1,179 @@
+
+#define SIGNF 1
+#define INTF 2
+
+#define NONE 0
+#define AUTO 'A'
+#define REG 'R'
+#define MEM 'T'
+#define PAR 'P'
+#define CONST '#'
+#define INDEX 'I'
+#define LABEL 'L'
+#define OADD '+'
+#define OSUB '-'
+#define OASSIG ':'
+#define OINC ';'
+#define OMOD '%'
+#define ODIV '/'
+#define OSHL 'l'
+#define OSHR 'r'
+#define OBAND '&'
+#define OBOR '|'
+#define OBXOR '^'
+#define OPTR '@'
+#define OADDR 'a'
+#define OLT '<'
+#define OGT '>'
+#define OGE ']'
+#define OLE '['
+#define OEQ '='
+#define ONE '!'
+#define OOR 'o'
+#define OAND 'y'
+#define OCAST 'c'
+#define ONEG '_'
+#define OCPL '~'
+#define OCOMMA ','
+#define ORET 'y'
+
+#define ADDABLE 10
+
+
+typedef struct symbol Symbol;
+typedef struct node Node;
+typedef struct inst Inst;
+typedef struct addr Addr;
+typedef struct type Type;
+
+struct type {
+ unsigned short size;
+ uint8_t align;
+ char letter;
+ uint8_t flags;
+};
+
+struct symbol {
+ unsigned short id;
+ char *name;
+ char kind;
+ bool public : 1;
+ bool extrn : 1;
+ bool index : 1;
+ union {
+ /* TODO: Admit inmediate of other type */
+ TINT imm;
+ struct {
+ Type type;
+ char sclass;
+ short off;
+ } v;
+ Inst *pc;
+ struct {
+ short locals;
+ short params;
+ Node **body;
+ } f;
+ } u;
+};
+
+struct node {
+ uint8_t op;
+ uint8_t subop;
+ Type type;
+ uint8_t complex;
+ uint8_t addable;
+ uint8_t reg;
+ Symbol *sym;
+ bool used : 1;
+ struct node *left, *right;
+};
+
+
+struct addr {
+ char kind;
+ union {
+ uint8_t reg;
+ TINT i;
+ Symbol *sym;
+ } u;
+};
+
+struct inst {
+ uint8_t op;
+ Addr from, to;
+ Symbol *label;
+ Inst *next, *prev;
+};
+
+enum nerrors {
+ EINTNUM, /* too much internal identifiers */
+ EEXTNUM, /* too much external identifiers */
+ EPARNUM, /* too much parameters */
+ ENODEOV, /* node overflow */
+ ESTACKO, /* stack overflow */
+ ESTACKU, /* stack underflow */
+ EEXPROV, /* expression overflow */
+ ETYPERR, /* incorrect type in expression */
+ EEXPBAL, /* expression not balanced */
+ ESYNTAX, /* syntax error */
+ ELNLINE, /* line too long */
+ EFERROR, /* error reading from file:%s*/
+ ENUMERR
+};
+
+enum {
+ LDW,
+ LDL,
+ LDH,
+ MOV,
+ LDI,
+ ADD,
+ PUSH,
+ POP,
+ RET,
+ NOP,
+ INC,
+ SUB,
+ DEC,
+ JP,
+ AND,
+ OR,
+ XOR,
+ CPL,
+ NEG
+};
+
+enum {
+ A = 1, B, C, D, E, H, L, IYL, IYH, NREGS,
+ AF = NREGS, HL, DE, BC, IY, NPAIRS,
+ SP = NPAIRS, IX
+};
+
+extern Symbol *curfun;
+extern Inst *prog, *pc;
+
+/* main.c */
+extern void error(unsigned nerror, ...);
+
+/* cgen.c */
+extern void addable(void);
+extern void generate(void);
+extern void apply(Node *(*fun)(Node *));
+
+/* parser.c */
+extern void parse(void);
+extern void prtree(Node *np);
+
+/* code.c */
+extern void code(uint8_t op, Node *to, Node *from);
+extern void inscode(uint8_t op, Addr *to, Addr *from);
+extern void writeout(void);
+extern void delcode(void);
+
+/* optm.c */
+extern void optimize(void);
+extern Node *imm(TINT i);
+
+/* peep.c */
+extern void peephole(void);
--- /dev/null
+++ b/cc2.old/cgen.c
@@ -1,0 +1,602 @@
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdlib.h>
+
+#include "../inc/cc.h"
+#include "cc2.h"
+
+static Symbol retlabel = {
+ .kind = LABEL
+};
+
+static Node *reguse[NPAIRS];
+static uint8_t upper[] = {[DE] = D, [HL] = H, [BC] = B, [IY] = IYH};
+static uint8_t lower[] = {[DE] = E, [HL] = L, [BC] = C, [IY] = IYL};
+static uint8_t pair[] = {
+ [A] = A,
+ [H] = HL, [L] = HL, [HL] = HL,
+ [B] = BC, [C] = BC, [BC] = BC,
+ [D] = DE, [E] = DE, [DE] = DE,
+ [IYL] = IY, [IYH] = IY, [IY] = IY
+};
+
+static Node regs[] = {
+ [E] = {
+ .op = REG,
+ .reg = E
+ },
+ [D] = {
+ .op = REG,
+ .reg = D
+ },
+ [H] = {
+ .op = REG,
+ .reg = H
+ },
+ [L] = {
+ .op = REG,
+ .reg = L
+ },
+ [C] = {
+ .op= REG,
+ .reg = C
+ },
+ [B] = {
+ .op= REG,
+ .reg = B
+ },
+ [A] = {
+ .op= REG,
+ .reg = A
+ },
+ [IYL] = {
+ .op = REG,
+ .reg = IYL
+ },
+ [IYH] = {
+ .op = REG,
+ .reg = IYH
+ },
+ [DE] = {
+ .op = REG,
+ .reg = DE
+ },
+ [HL] = {
+ .op = REG,
+ .reg = HL
+ },
+ [BC] = {
+ .op = REG,
+ .reg = BC
+ },
+ [IX] = {
+ .op = REG,
+ .reg = IX
+ },
+ [IY] = {
+ .op = REG,
+ .reg = IY
+ },
+ [SP] = {
+ .op = REG,
+ .reg = SP
+ }
+};
+
+static void moveto(Node *np, uint8_t reg);
+
+static void
+allocreg(Node *np)
+{
+ static uint8_t reg8[] = {A, B, C, D, E, H, L, IYL, IY, 0};
+ static uint8_t reg16[] = {BC, DE, IY, 0};
+ Node *r;
+ uint8_t *ary, *bp, c;
+
+ switch (np->type.size) {
+ case 1:
+ ary = reg8;
+ break;
+ case 2:
+ ary = reg16;
+ break;
+ default:
+ abort();
+ }
+ for (bp = ary; c = *bp; ++bp) {
+ r = reguse[c];
+ if (!r || r->used) {
+ moveto(np, c);
+ return;
+ }
+ }
+ /* TODO: What to do here? */
+ abort();
+}
+
+static void
+spill(uint8_t reg)
+{
+ Node *np, *r;
+ Symbol *sym;
+ uint8_t p, h, l;
+
+ if ((np = reguse[reg]) == NULL)
+ return;
+ sym = np->sym;
+ r = ®s[reg];
+
+ switch (np->type.size) {
+ case 1:
+ if (sym) {
+ code(LDL, np, r);
+ np->op = sym->kind;
+ } else {
+ allocreg(np);
+ }
+ break;
+ default:
+ abort();
+ }
+
+ reguse[reg] = NULL;
+ p = pair[reg];
+ l = lower[p];
+ h = upper[p];
+ if (reg >= NREGS)
+ reguse[l] = reguse[h] = NULL;
+ else if (!reguse[l] && !reguse[h])
+ reguse[p] = NULL;
+}
+
+static void
+moveto(Node *np, uint8_t reg)
+{
+ Node *r = ®s[reg], *u = reguse[reg];
+ char op = np->op;
+
+ if (u) {
+ Symbol *sym = np->sym;
+ if (sym && sym == u->sym)
+ return;
+ else if (!np->used)
+ spill(reg);
+ }
+
+ switch (np->type.size) {
+ case 1:
+ switch (op) {
+ case MEM:
+ case AUTO:
+ code(LDL, r, np);
+ break;
+ case CONST:
+ case INDEX:
+ code(LDI, r, np);
+ break;
+ case REG:
+ code(MOV, r, np);
+ break;
+ default:
+ abort();
+ }
+ break;
+ case 2:
+ switch (op) {
+ case CONST:
+ code(LDL, r, np);
+ break;
+ case AUTO:
+ code(LDL, ®s[lower[reg]], np);
+ code(LDH, ®s[upper[reg]], np);
+ break;
+ default:
+ abort();
+ }
+ reguse[upper[reg]] = reguse[lower[reg]] = np;
+ break;
+ default:
+ abort();
+ }
+ reguse[pair[reg]] = reguse[reg] = np;
+ np->op = REG;
+ np->reg = reg;
+}
+
+static void
+accum(Node *np)
+{
+ switch (np->type.size) {
+ case 1:
+ moveto(np, A);
+ break;
+ case 2:
+ moveto(np, HL);
+ break;
+ default:
+ abort();
+ }
+}
+
+static void
+index(Node *np)
+{
+ Node *u = reguse[HL];
+ Symbol *sym;
+
+ if (u && u->sym) {
+ if (u->op == INDEX && np->sym == u->sym) {
+ np->op = INDEX;
+ return;
+ } else {
+ spill(HL);
+ }
+ }
+ code(LDI, ®s[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 OASSIG:
+ allocreg(np);
+ break;
+ case ONEG:
+ case OCPL:
+ switch (np->op) {
+ case REG:
+ if (np->reg == A)
+ break;
+ /* PASSTHROUGH */
+ case PAR:
+ case AUTO:
+ case CONST:
+ case MEM:
+ case INDEX:
+ accum(np);
+ break;
+ default:
+ abort();
+ }
+ break;
+ case OADD:
+ case OSUB:
+ case OBAND:
+ case OBOR:
+ case OBXOR:
+ 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;
+
+ p = np->left;
+ q = np->right;
+ np->left = q;
+ np->right = p;
+}
+
+static void
+add(Node *np)
+{
+ Node *lp = np->left, *rp = np->right, *a;
+ uint8_t op;
+
+ switch (np->type.size) {
+ case 1:
+ a = reguse[A];
+ if (a == lp)
+ goto update_a;
+ if (a == rp)
+ goto conmute1;
+ if (lp->op == CONST) {
+ accum(rp);
+ goto conmute1;
+ }
+ accum(lp);
+ goto update_a;
+ conmute1:
+ conmute(np);
+ lp = np->left, rp = np->right;
+ update_a:
+ move(rp, np);
+ switch (np->op) {
+ case OADD:
+ op = ADD;
+ break;
+ case OSUB:
+ op = SUB;
+ break;
+ case OBAND:
+ op = AND;
+ break;
+ case OBOR:
+ op = OR;
+ break;
+ case OBXOR:
+ op = XOR;
+ break;
+ default:
+ abort();
+ }
+ code(op, lp, rp);
+ lp->used = rp->used = 1;
+ np->op = REG;
+ np->reg = A;
+ reguse[A] = np;
+ break;
+ default:
+ abort();
+ }
+}
+
+static void
+assign(Node *np)
+{
+ Node *lp = np->left, *rp = np->right;
+ Symbol *sym = lp->sym;
+
+ switch (np->type.size) {
+ case 1:
+ switch (lp->op) {
+ case MEM:
+ if (sym && sym->index)
+ lp->op = INDEX;
+ /* PASSTROUGH */
+ case INDEX:
+ case AUTO:
+ if (rp->op != REG)
+ move(rp, np);
+ lp->reg = rp->reg;
+ code(LDL, lp, rp);
+ break;
+ case REG:
+ code(MOV, lp, rp);
+ break;
+ default:
+ abort();
+ }
+ break;
+ default:
+ abort();
+ }
+
+ np->op = REG;
+ np->reg = lp->reg;
+ np->sym = rp->sym = lp->sym;
+ np->used = rp->used = lp->used = 1;
+}
+
+static void
+ret(Node *np)
+{
+ static Node retnode = {
+ .op = LABEL,
+ .sym = &retlabel
+ };
+
+ if (np->left)
+ accum(np->left);
+ code(JP, &retnode, NULL);
+}
+
+static void
+nop(Node *np)
+{
+}
+
+static void
+cpl(Node *np)
+{
+
+ Node *lp = np->left;
+ uint8_t op;
+
+ switch (np->type.size) {
+ case 1:
+ move(lp, np);
+ switch (np->op) {
+ case OCPL:
+ op = CPL;
+ break;
+ case ONEG:
+ op = NEG;
+ break;
+ default:
+ abort();
+ }
+ code(op, lp, NULL);
+ lp->used = 1;
+ np->sym = lp->sym;
+ np->reg = lp->reg;
+ np->op = REG;
+ reguse[A] = np;
+ break;
+ default:
+ abort();
+ }
+}
+
+static void
+cast(Node *np)
+{
+ Node *lp = np->left;
+ uint8_t reg;
+
+ if (lp->type.size != np->type.size)
+ abort();
+ lp->used = 1;
+ np->sym = lp->sym;
+ if ((np->op = lp->op) == REG) {
+ reg = lp->reg;
+ np->reg = reg;
+ reguse[pair[reg]] = reguse[reg] = np;
+ }
+}
+
+static void (*opnodes[])(Node *) = {
+ [OADD] = add,
+ [OSUB] = add,
+ [OASSIG] = assign,
+ [ORET] = ret,
+ [MEM] = nop,
+ [REG] = nop,
+ [AUTO] = nop,
+ [CONST] = nop,
+ [PAR] = nop,
+ [OBOR] = add,
+ [OBAND] = add,
+ [OBXOR] = add,
+ [OCPL] = cpl,
+ [ONEG] = cpl,
+ [OCAST] = cast
+};
+
+static void
+cgen(Node *np)
+{
+ Node *lp, *rp;
+
+ if (!np)
+ return;
+
+ if (np->addable >= ADDABLE)
+ return;
+
+ lp = np->left;
+ rp = np->right;
+ if (!lp) {
+ cgen(rp);
+ } else if (!rp) {
+ cgen(lp);
+ } else {
+ Node *p, *q;
+ if (lp->complex > rp->complex)
+ p = lp, q = rp;
+ else
+ p = rp, q = lp;
+ cgen(p);
+ cgen(q);
+ }
+ (*opnodes[np->op])(np);
+}
+
+void
+generate(void)
+{
+ uint8_t size = curfun->u.f.locals;
+ static short id = 1000;
+ Node **stmt, *np;
+
+ retlabel.id = id++;
+
+ code(PUSH, NULL, ®s[IX]);
+ code(MOV, ®s[IX], ®s[SP]);
+ if (size > 6) {
+ code(MOV, ®s[HL], imm(-size));
+ code(ADD, ®s[HL], ®s[SP]);
+ code(MOV, ®s[SP], ®s[HL]);
+ } else {
+ for (; size != 0; size-= 2)
+ code(PUSH, NULL, ®s[HL]);
+ }
+
+ for (stmt = curfun->u.f.body; np = *stmt; ++stmt)
+ cgen(np);
+
+ code(MOV, ®s[SP], ®s[IX]);
+ retlabel.u.pc = pc;
+ pc->label = &retlabel;
+ code(POP, ®s[IX], NULL);
+ code(RET, NULL, NULL);
+}
+
+/*
+ * This is strongly influenced by
+ * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps)
+ * calculate addresability as follows
+ * AUTO => 11 value+fp
+ * REGISTER => 13 register
+ * STATIC => 12 (value)
+ * CONST => 20 $value
+ */
+Node *
+genaddable(Node *np)
+{
+ Node *lp, *rp;
+
+ if (!np)
+ return np;
+
+ np->complex = 0;
+ np->addable = 0;
+ lp = np->left;
+ rp = np->right;
+ switch (np->op) {
+ case AUTO:
+ np->addable = 11;
+ break;
+ case REG:
+ np->addable = 13;
+ break;
+ case MEM:
+ np->addable = 12;
+ break;
+ case CONST:
+ np->addable = 20;
+ break;
+ default:
+ if (lp)
+ genaddable(lp);
+ if (rp)
+ genaddable(rp);
+ break;
+ }
+
+ if (np->addable > 10)
+ return np;
+ if (lp)
+ np->complex = lp->complex;
+ if (rp) {
+ int8_t d = np->complex - rp->complex;
+
+ if (d == 0)
+ ++np->complex;
+ else if (d < 0)
+ np->complex = rp->complex;
+ }
+ if (np->complex == 0)
+ ++np->complex;
+ return np;
+}
+
+void
+addable(void)
+{
+ apply(genaddable);
+}
--- /dev/null
+++ b/cc2.old/code.c
@@ -1,0 +1,229 @@
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdio.h>
+
+#include "../inc/cc.h"
+#include "cc2.h"
+
+static char *regnames[] = {
+ [AF] = "AF",
+ [HL] = "HL", [DE] = "DE", [BC] = "BC",
+ [IX] = "IX", [IY] = "IY", [SP] = "SP",
+ [A] = "A",
+ [B] = "B", [C] = "C",
+ [D] = "D", [E] = "E",
+ [H] = "H", [L] = "L",
+ [IYL]= "IYL",[IYH]= "IYH"
+};
+
+static void inst0(void), inst1(void), inst2(void);
+
+static void (*instcode[])(void) = {
+ [LDW] = inst2,
+ [LDL] = inst2,
+ [LDH] = inst2,
+ [LDI] = inst2,
+ [MOV] = inst2,
+ [ADD] = inst2,
+ [PUSH] = inst1,
+ [POP] = inst1,
+ [RET] = inst0,
+ [NOP] = inst0,
+ [INC] = inst1,
+ [SUB] = inst2,
+ [DEC] = inst1,
+ [JP] = inst1,
+ [AND] = inst2,
+ [OR] = inst2,
+ [XOR] = inst2,
+ [CPL] = inst1,
+ [NEG] = inst1
+
+};
+
+static char *insttext[] = {
+ [LDW] = "LD",
+ [LDL] = "LD",
+ [LDH] = "LD",
+ [LDI] = "LD",
+ [MOV] = "LD",
+ [ADD] = "ADD",
+ [PUSH] = "PUSH",
+ [POP] = "POP",
+ [RET] = "RET",
+ [NOP] = "NOP",
+ [INC] = "INC",
+ [SUB] = "SUB",
+ [DEC] = "DEC",
+ [JP] = "JP",
+ [AND] = "AND",
+ [OR] = "OR",
+ [XOR] = "XOR",
+ [CPL] = "CPL",
+ [NEG] = "NEG"
+};
+
+Inst *pc, *prog;
+
+static void
+nextpc(void)
+{
+ Inst *new;
+
+ new = xmalloc(sizeof(*new));
+
+ if (!pc) {
+ new->next = NULL;
+ prog = new;
+ } else {
+ new->next = pc->next;
+ pc->next = new;
+ }
+
+ new->prev = pc;
+ new->to.kind = NONE;
+ new->from.kind = NONE;
+ pc = new;
+}
+
+void
+addr(char op, Node *np, Addr *addr)
+{
+ switch (addr->kind = np->op) {
+ case REG:
+ addr->u.reg = np->reg;
+ break;
+ case CONST:
+ addr->u.i = np->sym->u.imm;
+ break;
+ case AUTO:
+ addr->u.i = np->sym->u.v.off;
+ break;
+ case LABEL:
+ case MEM:
+ addr->u.sym = np->sym;
+ break;
+ case INDEX:
+ break;
+ default:
+ abort();
+ }
+}
+
+void
+code(uint8_t op, Node *to, Node *from)
+{
+
+ nextpc();
+ if (from)
+ addr(op, from, &pc->from);
+ if (to)
+ addr(op, to, &pc->to);
+ pc->op = op;
+}
+
+void
+inscode(uint8_t op, Addr *to, Addr *from)
+{
+ nextpc();
+ if (from)
+ pc->from = *from;
+ if (to)
+ pc->to = *to;
+ pc->op = op;
+}
+
+void
+delcode(void)
+{
+ Inst *prev = pc->prev, *next = pc->next;
+
+ free(pc);
+ if (!prev) {
+ pc = next;
+ prog = NULL;
+ } else {
+ pc = prev;
+ prev->next = next;
+ if (next)
+ next->prev = prev;
+ }
+}
+
+void
+writeout(void)
+{
+ if (!prog)
+ return;
+
+ for (pc = prog; pc; pc = pc->next) {
+ if (pc->label)
+ printf("L%d:", pc->label->id);
+ (*instcode[pc->op])();
+ }
+}
+
+static void
+addr2txt(uint8_t op, Addr *a)
+{
+ Symbol *sym;
+
+ switch (a->kind) {
+ case REG:
+ fputs(regnames[a->u.reg], stdout);
+ break;
+ case CONST:
+ printf("%d", a->u.i);
+ break;
+ case PAR:
+ case AUTO:
+ printf("(IX%+d)", a->u.i);
+ break;
+ case LABEL:
+ sym = a->u.sym;
+ printf("L%d", sym->id);
+ break;
+ case INDEX:
+ fputs("(HL)", stdout);
+ break;
+ case MEM:
+ sym = a->u.sym;
+ if (sym->name)
+ printf((op == LDI) ? "%s" : "(%s)", sym->name);
+ else
+ printf((op == LDI) ? "T%u" : "(T%u)", sym->id);
+ break;
+ default:
+ abort();
+ }
+}
+
+static void
+inst0(void)
+{
+ printf("\t%s\n", insttext[pc->op]);
+}
+
+static void
+inst1(void)
+{
+ uint8_t op = pc->op;
+
+ printf("\t%s\t", insttext[op]);
+ addr2txt(op, (pc->to.kind != NONE) ? &pc->to : &pc->from);
+ putchar('\n');
+}
+
+static void
+inst2(void)
+{
+ uint8_t op = pc->op;
+
+ printf("\t%s\t", insttext[op]);
+ addr2txt(op, &pc->to);
+ putchar(',');
+ addr2txt(op, &pc->from);
+ putchar('\n');
+}
--- /dev/null
+++ b/cc2.old/generror
@@ -1,0 +1,19 @@
+
+BEGIN {
+ print "char *errlist[] = {"
+}
+/^enum nerrors \{/ {
+ inhome = 1
+}
+inhome && /E[A-Z]*, / {
+ sub(/,/, "", $1)
+ printf("\t[%s] = \"", $1)
+ for (i = 3; i < NF-1; ++i)
+ printf("%s ", $i)
+ printf("%s\",\n", $(NF-1));
+}
+inhome && /^}/ {
+ print "};"
+ inhome = 0
+}
+
--- /dev/null
+++ b/cc2.old/main.c
@@ -1,0 +1,56 @@
+
+#include <stdarg.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "../inc/cc.h"
+
+#include "cc2.h"
+#include "error.h"
+
+char odebug;
+
+void
+error(unsigned nerror, ...)
+{
+ va_list va;
+ va_start(va, nerror);
+ if (nerror >= ENUMERR)
+ fprintf(stderr, "incorrect error number '%d'", nerror);
+ else
+ vfprintf(stderr, errlist[nerror], va);
+ va_end(va);
+ putc('\n', stderr);
+ exit(1);
+}
+
+bool
+moreinput(void)
+{
+ int c;
+
+repeat:
+ if (feof(stdin))
+ return 0;
+ if ((c = getchar()) == '\n' || c == EOF)
+ goto repeat;
+ ungetc(c, stdin);
+ return 1;
+}
+
+int
+main(void)
+{
+ fputs("cc2 is not updated with the output of cc1", stderr);
+ exit(1);
+ while (moreinput()) {
+ parse();
+ optimize();
+ addable();
+ generate();
+ peephole();
+ writeout();
+ }
+ return 0;
+}
--- /dev/null
+++ b/cc2.old/optm.c
@@ -1,0 +1,51 @@
+
+#include <stddef.h>
+#include <inttypes.h>
+
+#include "../inc/cc.h"
+#include "cc2.h"
+
+
+#include <stdio.h>
+
+static Node *
+optcasts(Node *np, Type *tp)
+{
+ if (!np)
+ return NULL;
+
+repeat:
+ switch (np->op) {
+ case OCAST:
+ /* TODO: be careful with the sign */
+ if (np->type.flags&INTF && np->type.size >= tp->size) {
+ np = np->left;
+ goto repeat;
+ }
+ break;
+ case OASSIG:
+ tp = &np->type;
+ break;
+ default:
+ if (np->type.size > tp->size)
+ np->type = *tp;
+ break;
+ }
+
+ np->left = optcasts(np->left, tp);
+ np->right = optcasts(np->right, tp);
+ return np;
+}
+
+static Node *
+opt(Node *np)
+{
+ np = optcasts(np, &np->type);
+ return np;
+}
+
+void
+optimize(void)
+{
+ apply(opt);
+}
--- /dev/null
+++ b/cc2.old/parser.c
@@ -1,0 +1,603 @@
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../inc/cc.h"
+#include "../inc/sizes.h"
+
+#include "cc2.h"
+
+#define MAXLINE 200
+#define NR_STACKSIZ 32
+#define NR_NODEPOOL 128
+#define NR_EXPRESSIONS 64
+
+enum {
+ LOCAL, GLOBAL, PARAMETER
+};
+
+Symbol *curfun;
+static Node *stack[NR_STACKSIZ], **stackp;
+static Node *listexp[NR_EXPRESSIONS], **listp;
+static Node nodepool[NR_NODEPOOL], *newp;
+
+
+static Type Funct = {
+ .letter = L_FUNCTION,
+};
+
+static Type l_int8 = {
+ .letter = L_INT8,
+ .size = 1,
+ .align = 2,
+ .flags = SIGNF | INTF
+};
+
+static Type l_int16 = {
+ .letter = L_INT16,
+ .size = 2,
+ .align = 2,
+ .flags = SIGNF | INTF
+
+};
+
+static Type l_int32 = {
+ .letter = L_INT32,
+ .size = 4,
+ .align = 4,
+ .flags = SIGNF | INTF
+
+};
+
+static Type l_int64 = {
+ .letter = L_INT64,
+ .size = 8,
+ .align = 8,
+ .flags = SIGNF | INTF
+
+};
+
+static Type l_uint8 = {
+ .letter = L_UINT8,
+ .size = 1,
+ .align = 2,
+ .flags = INTF
+};
+
+static Type l_uint16 = {
+ .letter = L_UINT16,
+ .size = 2,
+ .align = 2,
+ .flags = INTF
+};
+
+static Type l_uint32 = {
+ .letter = L_UINT32,
+ .size = 4,
+ .align = 4,
+ .flags = INTF
+};
+
+static Type l_uint64 = {
+ .letter = L_UINT64,
+ .size = 8,
+ .align = 8,
+ .flags = INTF
+};
+
+static void cast(char *), operator(char *), assignment(char *), increment(char *),
+ globvar(char *), localvar(char *), paramvar(char *), label(char *),
+ immediate(char *), unary(char *), oreturn(char *);
+
+/*TODO: Remove hardcoded symbols */
+
+static void (*optbl[])(char *) = {
+ [L_INT8] = cast,
+ [L_INT16] = cast,
+ [L_INT32] = cast,
+ [L_INT64] = cast,
+ [L_UINT8] = cast,
+ [L_UINT16] = cast,
+ [L_UINT32] = cast,
+ [L_UINT64] = cast,
+ [L_BOOL] = cast,
+ [L_FLOAT] = cast,
+ [L_DOUBLE] = cast,
+ [L_LDOUBLE] = cast,
+ [L_POINTER] = cast,
+ [L_VOID] = cast,
+ ['+'] = operator,
+ ['%'] = operator,
+ ['-'] = operator,
+ ['*'] = operator,
+ ['/'] = operator,
+ ['l'] = operator,
+ ['r'] = operator,
+ ['&'] = operator,
+ ['|'] = operator,
+ ['^'] = operator,
+ [':'] = assignment,
+ [';'] = increment,
+ ['Y'] = globvar,
+ ['A'] = localvar,
+ ['K'] = localvar,
+ ['T'] = localvar,
+ ['G'] = globvar,
+ ['P'] = paramvar,
+ ['L'] = label,
+ ['#'] = immediate,
+ ['@'] = unary,
+ ['a'] = unary,
+ ['<'] = operator,
+ ['>'] = operator,
+ [']'] = operator,
+ ['['] = operator,
+ ['='] = operator,
+ ['!'] = unary,
+ ['y'] = oreturn,
+ ['j'] = NULL,
+ ['o'] = operator,
+ ['_'] = unary,
+ ['~'] = unary,
+ [','] = operator,
+ ['\177'] = NULL
+};
+
+static void
+prnode(Node *np)
+{
+ if (np->left)
+ prnode(np->left);
+ if (np->right)
+ prnode(np->right);
+ fprintf(stderr, "\t%c%c", np->op, np->type.letter);
+}
+
+void
+prtree(Node *np)
+{
+ prnode(np);
+ putc('\n', stderr);
+}
+
+void
+apply(Node *(*fun)(Node *))
+{
+ Node **list, *np;
+
+ for (list = curfun->u.f.body; np = *list; ++list)
+ *list++ = (*fun)(np);
+}
+
+static Symbol *
+parameter(char *num)
+{
+ static Symbol tbl[NR_FUNPARAM];
+ Symbol *sym;
+ unsigned i = atoi(num);
+
+ if (!curfun)
+ error(ESYNTAX);
+ if (i >= NR_FUNPARAM)
+ error(EPARNUM);
+ sym = &tbl[i];
+ sym->id = i;
+ return sym;
+}
+
+static Symbol *
+local(char *num)
+{
+ static Symbol tbl[NR_INT_IDENT];
+ Symbol *sym;
+ unsigned i = atoi(num);
+
+ if (!curfun)
+ error(ESYNTAX);
+ if (i >= NR_INT_IDENT)
+ error(EINTNUM);
+ sym = &tbl[i];
+ sym->id = i;
+ return sym;
+}
+
+static Symbol *
+global(char *num)
+{
+ static Symbol tbl[NR_EXT_IDENT];
+ Symbol *sym;
+ unsigned i = atoi(num);
+
+ if (i >= NR_EXT_IDENT)
+ error(EEXTNUM);
+
+ sym = &tbl[i];
+ sym->id = i;
+ return sym;
+}
+
+static Node *
+newnode(void)
+{
+ if (newp == &nodepool[NR_NODEPOOL])
+ error(ENODEOV);
+ return newp++;
+}
+
+Node *
+imm(TINT i)
+{
+ Node *np = newnode();
+
+ np->op = CONST;
+ np->type = l_int16;
+ /* FIX: memory leak */
+ np->sym = xmalloc(sizeof(Symbol));
+ np->sym->u.imm = i;
+ np->left = np->right = NULL;
+ return np;
+}
+
+static void
+push(Node *np)
+{
+ if (stackp == &stack[NR_STACKSIZ])
+ error(ESTACKO);
+ *stackp++ = np;
+}
+
+static Node *
+pop(void)
+{
+ if (stackp == stack)
+ error(ESTACKU);
+ return *--stackp;
+}
+
+static Type *
+gettype(char *type)
+{
+ switch (type[0]) {
+ case L_INT8:
+ return &l_int8;
+ case L_INT16:
+ return &l_int16;
+ case L_INT32:
+ return &l_int32;
+ case L_INT64:
+ return &l_int64;
+ case L_UINT8:
+ return &l_uint8;
+ case L_UINT16:
+ return &l_uint16;
+ case L_UINT32:
+ return &l_uint32;
+ case L_UINT64:
+ return &l_uint64;
+ case L_FUNCTION:
+ return &Funct;
+ default:
+ error(ETYPERR);
+ }
+}
+
+static Symbol *
+symbol(uint8_t t, char *token)
+{
+ Symbol *sym;
+ static Symbol *(*tbl[3])(char *)= {
+ [LOCAL] = local,
+ [GLOBAL] = global,
+ [PARAMETER] = parameter
+ };
+ sym = (*tbl[t])(token+1);
+ sym->kind = *token;
+ return sym;
+}
+
+static void
+variable(uint8_t t, char *token)
+{
+ Node *np = newnode();
+ Symbol *sym = symbol(t, token);
+
+ np->sym = sym;
+ np->op = sym->u.v.sclass;
+ np->type = sym->u.v.type;
+ np->left = np->right = NULL;
+ push(np);
+}
+
+static void
+localvar(char *token)
+{
+ variable(LOCAL, token);
+}
+
+static void
+globvar(char *token)
+{
+ variable(GLOBAL, token);
+}
+
+static void
+paramvar(char *token)
+{
+ variable(PARAMETER, token);
+}
+
+static void
+immediate(char *token)
+{
+ /* TODO: check type of immediate */
+ push(imm(atoi(token+2)));
+}
+
+static void
+unary(char *token)
+{
+ Node *np = newnode();
+
+ np->right = NULL;
+ np->left = pop();
+ np->type = *gettype(token+1);
+ np->op = token[0];
+ push(np);
+}
+
+static void
+operator(char *token)
+{
+ Node *np = newnode();
+
+ np->right = pop();
+ np->left = pop();
+ np->type = *gettype(token+1);
+ np->op = token[0];
+ push(np);
+}
+
+static void
+label(char *token)
+{
+ Node *np = newnode();
+
+ np->left = np->right = NULL;
+ np->op = LABEL;
+ np->sym = local(token);
+ push(np);
+}
+
+static void
+increment(char *token)
+{
+ Node *np = newnode();
+
+ np->right = pop();
+ np->left = pop();
+ np->type = *gettype(token+2);
+ np->op = token[0];
+ switch (np->subop = token[1]) {
+ case '-': case '+':
+ push(np);
+ break;
+ default:
+ error(ESYNTAX);
+ }
+}
+
+static void
+assignment(char *token)
+{
+ Node *np = newnode();
+
+ np->right = pop();
+ np->left = pop();
+ np->op = *token;
+ switch (*++token) {
+ case OADD: case OSUB: case OINC: case OMOD: case ODIV:
+ case OSHL: case OSHR: case OBAND: case OBOR: case OBXOR:
+ np->subop = *++token;
+ default:
+ np->type = *gettype(token);
+ break;
+ }
+ push(np);
+}
+
+static void
+cast(char *token)
+{
+ Node *np = newnode();
+
+ np->right = NULL;
+ np->left = pop();
+ np->op = OCAST;
+ np->type = *gettype(token+1);
+ push(np);
+}
+
+static void
+expr(char *token)
+{
+ void (*fun)(char *);
+ unsigned c;
+
+ do {
+ if ((c = token[0]) > 0x7f || (fun = optbl[c]) == NULL)
+ error(ESYNTAX);
+ (*fun)(token);
+ } while (token = strtok(NULL, "\t"));
+}
+
+static void
+expression(char *token)
+{
+ Node *np;
+
+ if (!curfun)
+ error(ESYNTAX);
+
+ expr(token);
+
+ np = pop();
+ if (stackp != stack)
+ error(EEXPBAL);
+ if (listp == &listexp[NR_EXPRESSIONS])
+ error(EEXPROV);
+ *listp++ = np;
+}
+
+static void
+oreturn(char *token)
+{
+ Node *np = newnode(), *lp;
+
+ np->op = token[0];
+
+ if (token = strtok(NULL, "\t")) {
+ expr(token);
+ lp = pop();
+ np->left = lp;
+ np->type = lp->type;
+ } else {
+ np->left = NULL;
+ }
+ np->right = NULL;
+ push(np);
+}
+
+static void
+deflabel(char *token)
+{
+ Symbol *sym;
+
+ if (!curfun)
+ error(ESYNTAX);
+ sym = local(token);
+}
+
+static Symbol *
+declaration(uint8_t t, char class, char *token)
+{
+ Symbol *sym = symbol(t, token);
+ char *s;
+
+ free(sym->name);
+ memset(sym, 0, sizeof(*sym));
+ sym->u.v.sclass = class;
+
+ if ((s = strtok(NULL, "\t")) == NULL)
+ error(ESYNTAX);
+ sym->u.v.type = *gettype(s);
+ if ((s = strtok(NULL, "\t")) != NULL)
+ sym->name = xstrdup(s);
+
+ return sym;
+}
+
+static void
+globdcl(char *token)
+{
+ Symbol *sym = declaration(GLOBAL, MEM, token);
+
+ switch (token[0]) {
+ case 'X':
+ sym->extrn = 1;
+ break;
+ case 'G':
+ sym->public = 1;
+ break;
+ }
+
+ if (sym->u.v.type.letter != L_FUNCTION)
+ return;
+
+ if (curfun)
+ error(ESYNTAX);
+
+ curfun = sym;
+ sym->u.f.body = listp = listexp;
+ newp = nodepool;
+}
+
+static void
+paramdcl(char *token)
+{
+ Symbol *sym = declaration(PARAMETER, AUTO, token);
+ sym->u.v.off = -curfun->u.f.params;
+ curfun->u.f.params += sym->u.v.type.size;
+}
+
+static void
+localdcl(char *token)
+{
+ Symbol *sym = declaration(LOCAL, token[0], token);
+ char sclass = *token;
+
+ if (sclass == 'A' || sclass == 'R') {
+ uint8_t size = sym->u.v.type.size;
+ /* stack elements are 2 byte multiple */
+ if (size == 1)
+ ++size;
+ curfun->u.f.locals += size;
+ sym->u.v.off = curfun->u.f.locals;
+ }
+}
+
+void
+parse(void)
+{
+ void (*fun)(char *tok);
+ uint8_t len;
+ int c;
+ char line[MAXLINE];
+
+ curfun = NULL;
+ stackp = stack;
+ listp = listexp;
+ newp = nodepool;
+
+ for (;;) {
+ switch (c = getchar()) {
+ case 'L':
+ fun = deflabel;
+ break;
+ case '\t':
+ fun = expression;
+ break;
+ case 'S':
+ /* TODO: struct */
+ break;
+ case 'P':
+ fun = paramdcl;
+ break;
+ case 'A': case 'R': case 'T':
+ fun = localdcl;
+ break;
+ case 'Y': case 'G':
+ fun = globdcl;
+ break;
+ case '}':
+ if (curfun)
+ return;
+ default:
+ goto syntax_error;
+ }
+
+ ungetc(c, stdin);
+ if (!fgets(line, sizeof(line), stdin))
+ break;
+ len = strlen(line);
+ if (line[len-1] != '\n')
+ error(ELNLINE);
+ line[len-1] = '\0';
+ (*fun)(strtok(line, "\t"));
+ }
+
+syntax_error:
+ error(ESYNTAX);
+}
--- /dev/null
+++ b/cc2.old/peep.c
@@ -1,0 +1,39 @@
+
+#include <inttypes.h>
+#include <stddef.h>
+
+#include "../inc/cc.h"
+#include "cc2.h"
+
+void
+peephole(void)
+{
+ Addr to, from;
+ TINT i;
+ uint8_t op;
+
+ for (pc = prog; pc; pc = pc->next) {
+ to = pc->to;
+ from = pc->from;
+
+ switch (pc->op) {
+ case SUB:
+ case ADD:
+ if (from.kind == CONST) {
+ if ((i = from.u.i) == 0 || i < 4) {
+ delcode();
+ op = (pc->op == ADD) ? INC : DEC;
+
+ while (i--)
+ inscode(op, &to, NULL);
+ }
+ /* TODO: More optimizations (ex: -1) */
+ }
+ break;
+ case JP:
+ if (to.u.sym->u.pc == pc->next)
+ delcode();
+ break;
+ }
+ }
+}
--- a/cc2/Makefile
+++ /dev/null
@@ -1,23 +1,0 @@
-.POSIX:
-
-include ../config.mk
-
-OBJS = main.o parser.o cgen.o code.o optm.o peep.o
-
-all: cc2
-
-
-$(OBJS): ../inc/cc.h ../inc/sizes.h cc2.h
-main.o: error.h
-
-error.h: cc2.h
- rm -f $@; trap 'rm -f $$$$.h' EXIT INT QUIT
- awk -f generror cc2.h > $$$$.h && mv $$$$.h $@
-
-cc2: $(OBJS) ../lib/libcc.a
- $(CC) $(LDFLAGS) $(OBJS) ../lib/libcc.a -o $@
-
-clean:
- rm -f $(OBJS)
- rm -f cc2 error.h
-
--- a/cc2/cc2.h
+++ /dev/null
@@ -1,179 +1,0 @@
-
-#define SIGNF 1
-#define INTF 2
-
-#define NONE 0
-#define AUTO 'A'
-#define REG 'R'
-#define MEM 'T'
-#define PAR 'P'
-#define CONST '#'
-#define INDEX 'I'
-#define LABEL 'L'
-#define OADD '+'
-#define OSUB '-'
-#define OASSIG ':'
-#define OINC ';'
-#define OMOD '%'
-#define ODIV '/'
-#define OSHL 'l'
-#define OSHR 'r'
-#define OBAND '&'
-#define OBOR '|'
-#define OBXOR '^'
-#define OPTR '@'
-#define OADDR 'a'
-#define OLT '<'
-#define OGT '>'
-#define OGE ']'
-#define OLE '['
-#define OEQ '='
-#define ONE '!'
-#define OOR 'o'
-#define OAND 'y'
-#define OCAST 'c'
-#define ONEG '_'
-#define OCPL '~'
-#define OCOMMA ','
-#define ORET 'y'
-
-#define ADDABLE 10
-
-
-typedef struct symbol Symbol;
-typedef struct node Node;
-typedef struct inst Inst;
-typedef struct addr Addr;
-typedef struct type Type;
-
-struct type {
- unsigned short size;
- uint8_t align;
- char letter;
- uint8_t flags;
-};
-
-struct symbol {
- unsigned short id;
- char *name;
- char kind;
- bool public : 1;
- bool extrn : 1;
- bool index : 1;
- union {
- /* TODO: Admit inmediate of other type */
- TINT imm;
- struct {
- Type type;
- char sclass;
- short off;
- } v;
- Inst *pc;
- struct {
- short locals;
- short params;
- Node **body;
- } f;
- } u;
-};
-
-struct node {
- uint8_t op;
- uint8_t subop;
- Type type;
- uint8_t complex;
- uint8_t addable;
- uint8_t reg;
- Symbol *sym;
- bool used : 1;
- struct node *left, *right;
-};
-
-
-struct addr {
- char kind;
- union {
- uint8_t reg;
- TINT i;
- Symbol *sym;
- } u;
-};
-
-struct inst {
- uint8_t op;
- Addr from, to;
- Symbol *label;
- Inst *next, *prev;
-};
-
-enum nerrors {
- EINTNUM, /* too much internal identifiers */
- EEXTNUM, /* too much external identifiers */
- EPARNUM, /* too much parameters */
- ENODEOV, /* node overflow */
- ESTACKO, /* stack overflow */
- ESTACKU, /* stack underflow */
- EEXPROV, /* expression overflow */
- ETYPERR, /* incorrect type in expression */
- EEXPBAL, /* expression not balanced */
- ESYNTAX, /* syntax error */
- ELNLINE, /* line too long */
- EFERROR, /* error reading from file:%s*/
- ENUMERR
-};
-
-enum {
- LDW,
- LDL,
- LDH,
- MOV,
- LDI,
- ADD,
- PUSH,
- POP,
- RET,
- NOP,
- INC,
- SUB,
- DEC,
- JP,
- AND,
- OR,
- XOR,
- CPL,
- NEG
-};
-
-enum {
- A = 1, B, C, D, E, H, L, IYL, IYH, NREGS,
- AF = NREGS, HL, DE, BC, IY, NPAIRS,
- SP = NPAIRS, IX
-};
-
-extern Symbol *curfun;
-extern Inst *prog, *pc;
-
-/* main.c */
-extern void error(unsigned nerror, ...);
-
-/* cgen.c */
-extern void addable(void);
-extern void generate(void);
-extern void apply(Node *(*fun)(Node *));
-
-/* parser.c */
-extern void parse(void);
-extern void prtree(Node *np);
-
-/* code.c */
-extern void code(uint8_t op, Node *to, Node *from);
-extern void inscode(uint8_t op, Addr *to, Addr *from);
-extern void writeout(void);
-extern void delcode(void);
-
-/* optm.c */
-extern void optimize(void);
-extern Node *imm(TINT i);
-
-/* peep.c */
-extern void peephole(void);
--- a/cc2/cgen.c
+++ /dev/null
@@ -1,602 +1,0 @@
-
-#include <assert.h>
-#include <inttypes.h>
-#include <stdlib.h>
-
-#include "../inc/cc.h"
-#include "cc2.h"
-
-static Symbol retlabel = {
- .kind = LABEL
-};
-
-static Node *reguse[NPAIRS];
-static uint8_t upper[] = {[DE] = D, [HL] = H, [BC] = B, [IY] = IYH};
-static uint8_t lower[] = {[DE] = E, [HL] = L, [BC] = C, [IY] = IYL};
-static uint8_t pair[] = {
- [A] = A,
- [H] = HL, [L] = HL, [HL] = HL,
- [B] = BC, [C] = BC, [BC] = BC,
- [D] = DE, [E] = DE, [DE] = DE,
- [IYL] = IY, [IYH] = IY, [IY] = IY
-};
-
-static Node regs[] = {
- [E] = {
- .op = REG,
- .reg = E
- },
- [D] = {
- .op = REG,
- .reg = D
- },
- [H] = {
- .op = REG,
- .reg = H
- },
- [L] = {
- .op = REG,
- .reg = L
- },
- [C] = {
- .op= REG,
- .reg = C
- },
- [B] = {
- .op= REG,
- .reg = B
- },
- [A] = {
- .op= REG,
- .reg = A
- },
- [IYL] = {
- .op = REG,
- .reg = IYL
- },
- [IYH] = {
- .op = REG,
- .reg = IYH
- },
- [DE] = {
- .op = REG,
- .reg = DE
- },
- [HL] = {
- .op = REG,
- .reg = HL
- },
- [BC] = {
- .op = REG,
- .reg = BC
- },
- [IX] = {
- .op = REG,
- .reg = IX
- },
- [IY] = {
- .op = REG,
- .reg = IY
- },
- [SP] = {
- .op = REG,
- .reg = SP
- }
-};
-
-static void moveto(Node *np, uint8_t reg);
-
-static void
-allocreg(Node *np)
-{
- static uint8_t reg8[] = {A, B, C, D, E, H, L, IYL, IY, 0};
- static uint8_t reg16[] = {BC, DE, IY, 0};
- Node *r;
- uint8_t *ary, *bp, c;
-
- switch (np->type.size) {
- case 1:
- ary = reg8;
- break;
- case 2:
- ary = reg16;
- break;
- default:
- abort();
- }
- for (bp = ary; c = *bp; ++bp) {
- r = reguse[c];
- if (!r || r->used) {
- moveto(np, c);
- return;
- }
- }
- /* TODO: What to do here? */
- abort();
-}
-
-static void
-spill(uint8_t reg)
-{
- Node *np, *r;
- Symbol *sym;
- uint8_t p, h, l;
-
- if ((np = reguse[reg]) == NULL)
- return;
- sym = np->sym;
- r = ®s[reg];
-
- switch (np->type.size) {
- case 1:
- if (sym) {
- code(LDL, np, r);
- np->op = sym->kind;
- } else {
- allocreg(np);
- }
- break;
- default:
- abort();
- }
-
- reguse[reg] = NULL;
- p = pair[reg];
- l = lower[p];
- h = upper[p];
- if (reg >= NREGS)
- reguse[l] = reguse[h] = NULL;
- else if (!reguse[l] && !reguse[h])
- reguse[p] = NULL;
-}
-
-static void
-moveto(Node *np, uint8_t reg)
-{
- Node *r = ®s[reg], *u = reguse[reg];
- char op = np->op;
-
- if (u) {
- Symbol *sym = np->sym;
- if (sym && sym == u->sym)
- return;
- else if (!np->used)
- spill(reg);
- }
-
- switch (np->type.size) {
- case 1:
- switch (op) {
- case MEM:
- case AUTO:
- code(LDL, r, np);
- break;
- case CONST:
- case INDEX:
- code(LDI, r, np);
- break;
- case REG:
- code(MOV, r, np);
- break;
- default:
- abort();
- }
- break;
- case 2:
- switch (op) {
- case CONST:
- code(LDL, r, np);
- break;
- case AUTO:
- code(LDL, ®s[lower[reg]], np);
- code(LDH, ®s[upper[reg]], np);
- break;
- default:
- abort();
- }
- reguse[upper[reg]] = reguse[lower[reg]] = np;
- break;
- default:
- abort();
- }
- reguse[pair[reg]] = reguse[reg] = np;
- np->op = REG;
- np->reg = reg;
-}
-
-static void
-accum(Node *np)
-{
- switch (np->type.size) {
- case 1:
- moveto(np, A);
- break;
- case 2:
- moveto(np, HL);
- break;
- default:
- abort();
- }
-}
-
-static void
-index(Node *np)
-{
- Node *u = reguse[HL];
- Symbol *sym;
-
- if (u && u->sym) {
- if (u->op == INDEX && np->sym == u->sym) {
- np->op = INDEX;
- return;
- } else {
- spill(HL);
- }
- }
- code(LDI, ®s[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 OASSIG:
- allocreg(np);
- break;
- case ONEG:
- case OCPL:
- switch (np->op) {
- case REG:
- if (np->reg == A)
- break;
- /* PASSTHROUGH */
- case PAR:
- case AUTO:
- case CONST:
- case MEM:
- case INDEX:
- accum(np);
- break;
- default:
- abort();
- }
- break;
- case OADD:
- case OSUB:
- case OBAND:
- case OBOR:
- case OBXOR:
- 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;
-
- p = np->left;
- q = np->right;
- np->left = q;
- np->right = p;
-}
-
-static void
-add(Node *np)
-{
- Node *lp = np->left, *rp = np->right, *a;
- uint8_t op;
-
- switch (np->type.size) {
- case 1:
- a = reguse[A];
- if (a == lp)
- goto update_a;
- if (a == rp)
- goto conmute1;
- if (lp->op == CONST) {
- accum(rp);
- goto conmute1;
- }
- accum(lp);
- goto update_a;
- conmute1:
- conmute(np);
- lp = np->left, rp = np->right;
- update_a:
- move(rp, np);
- switch (np->op) {
- case OADD:
- op = ADD;
- break;
- case OSUB:
- op = SUB;
- break;
- case OBAND:
- op = AND;
- break;
- case OBOR:
- op = OR;
- break;
- case OBXOR:
- op = XOR;
- break;
- default:
- abort();
- }
- code(op, lp, rp);
- lp->used = rp->used = 1;
- np->op = REG;
- np->reg = A;
- reguse[A] = np;
- break;
- default:
- abort();
- }
-}
-
-static void
-assign(Node *np)
-{
- Node *lp = np->left, *rp = np->right;
- Symbol *sym = lp->sym;
-
- switch (np->type.size) {
- case 1:
- switch (lp->op) {
- case MEM:
- if (sym && sym->index)
- lp->op = INDEX;
- /* PASSTROUGH */
- case INDEX:
- case AUTO:
- if (rp->op != REG)
- move(rp, np);
- lp->reg = rp->reg;
- code(LDL, lp, rp);
- break;
- case REG:
- code(MOV, lp, rp);
- break;
- default:
- abort();
- }
- break;
- default:
- abort();
- }
-
- np->op = REG;
- np->reg = lp->reg;
- np->sym = rp->sym = lp->sym;
- np->used = rp->used = lp->used = 1;
-}
-
-static void
-ret(Node *np)
-{
- static Node retnode = {
- .op = LABEL,
- .sym = &retlabel
- };
-
- if (np->left)
- accum(np->left);
- code(JP, &retnode, NULL);
-}
-
-static void
-nop(Node *np)
-{
-}
-
-static void
-cpl(Node *np)
-{
-
- Node *lp = np->left;
- uint8_t op;
-
- switch (np->type.size) {
- case 1:
- move(lp, np);
- switch (np->op) {
- case OCPL:
- op = CPL;
- break;
- case ONEG:
- op = NEG;
- break;
- default:
- abort();
- }
- code(op, lp, NULL);
- lp->used = 1;
- np->sym = lp->sym;
- np->reg = lp->reg;
- np->op = REG;
- reguse[A] = np;
- break;
- default:
- abort();
- }
-}
-
-static void
-cast(Node *np)
-{
- Node *lp = np->left;
- uint8_t reg;
-
- if (lp->type.size != np->type.size)
- abort();
- lp->used = 1;
- np->sym = lp->sym;
- if ((np->op = lp->op) == REG) {
- reg = lp->reg;
- np->reg = reg;
- reguse[pair[reg]] = reguse[reg] = np;
- }
-}
-
-static void (*opnodes[])(Node *) = {
- [OADD] = add,
- [OSUB] = add,
- [OASSIG] = assign,
- [ORET] = ret,
- [MEM] = nop,
- [REG] = nop,
- [AUTO] = nop,
- [CONST] = nop,
- [PAR] = nop,
- [OBOR] = add,
- [OBAND] = add,
- [OBXOR] = add,
- [OCPL] = cpl,
- [ONEG] = cpl,
- [OCAST] = cast
-};
-
-static void
-cgen(Node *np)
-{
- Node *lp, *rp;
-
- if (!np)
- return;
-
- if (np->addable >= ADDABLE)
- return;
-
- lp = np->left;
- rp = np->right;
- if (!lp) {
- cgen(rp);
- } else if (!rp) {
- cgen(lp);
- } else {
- Node *p, *q;
- if (lp->complex > rp->complex)
- p = lp, q = rp;
- else
- p = rp, q = lp;
- cgen(p);
- cgen(q);
- }
- (*opnodes[np->op])(np);
-}
-
-void
-generate(void)
-{
- uint8_t size = curfun->u.f.locals;
- static short id = 1000;
- Node **stmt, *np;
-
- retlabel.id = id++;
-
- code(PUSH, NULL, ®s[IX]);
- code(MOV, ®s[IX], ®s[SP]);
- if (size > 6) {
- code(MOV, ®s[HL], imm(-size));
- code(ADD, ®s[HL], ®s[SP]);
- code(MOV, ®s[SP], ®s[HL]);
- } else {
- for (; size != 0; size-= 2)
- code(PUSH, NULL, ®s[HL]);
- }
-
- for (stmt = curfun->u.f.body; np = *stmt; ++stmt)
- cgen(np);
-
- code(MOV, ®s[SP], ®s[IX]);
- retlabel.u.pc = pc;
- pc->label = &retlabel;
- code(POP, ®s[IX], NULL);
- code(RET, NULL, NULL);
-}
-
-/*
- * This is strongly influenced by
- * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps)
- * calculate addresability as follows
- * AUTO => 11 value+fp
- * REGISTER => 13 register
- * STATIC => 12 (value)
- * CONST => 20 $value
- */
-Node *
-genaddable(Node *np)
-{
- Node *lp, *rp;
-
- if (!np)
- return np;
-
- np->complex = 0;
- np->addable = 0;
- lp = np->left;
- rp = np->right;
- switch (np->op) {
- case AUTO:
- np->addable = 11;
- break;
- case REG:
- np->addable = 13;
- break;
- case MEM:
- np->addable = 12;
- break;
- case CONST:
- np->addable = 20;
- break;
- default:
- if (lp)
- genaddable(lp);
- if (rp)
- genaddable(rp);
- break;
- }
-
- if (np->addable > 10)
- return np;
- if (lp)
- np->complex = lp->complex;
- if (rp) {
- int8_t d = np->complex - rp->complex;
-
- if (d == 0)
- ++np->complex;
- else if (d < 0)
- np->complex = rp->complex;
- }
- if (np->complex == 0)
- ++np->complex;
- return np;
-}
-
-void
-addable(void)
-{
- apply(genaddable);
-}
--- a/cc2/code.c
+++ /dev/null
@@ -1,229 +1,0 @@
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <inttypes.h>
-#include <stdio.h>
-
-#include "../inc/cc.h"
-#include "cc2.h"
-
-static char *regnames[] = {
- [AF] = "AF",
- [HL] = "HL", [DE] = "DE", [BC] = "BC",
- [IX] = "IX", [IY] = "IY", [SP] = "SP",
- [A] = "A",
- [B] = "B", [C] = "C",
- [D] = "D", [E] = "E",
- [H] = "H", [L] = "L",
- [IYL]= "IYL",[IYH]= "IYH"
-};
-
-static void inst0(void), inst1(void), inst2(void);
-
-static void (*instcode[])(void) = {
- [LDW] = inst2,
- [LDL] = inst2,
- [LDH] = inst2,
- [LDI] = inst2,
- [MOV] = inst2,
- [ADD] = inst2,
- [PUSH] = inst1,
- [POP] = inst1,
- [RET] = inst0,
- [NOP] = inst0,
- [INC] = inst1,
- [SUB] = inst2,
- [DEC] = inst1,
- [JP] = inst1,
- [AND] = inst2,
- [OR] = inst2,
- [XOR] = inst2,
- [CPL] = inst1,
- [NEG] = inst1
-
-};
-
-static char *insttext[] = {
- [LDW] = "LD",
- [LDL] = "LD",
- [LDH] = "LD",
- [LDI] = "LD",
- [MOV] = "LD",
- [ADD] = "ADD",
- [PUSH] = "PUSH",
- [POP] = "POP",
- [RET] = "RET",
- [NOP] = "NOP",
- [INC] = "INC",
- [SUB] = "SUB",
- [DEC] = "DEC",
- [JP] = "JP",
- [AND] = "AND",
- [OR] = "OR",
- [XOR] = "XOR",
- [CPL] = "CPL",
- [NEG] = "NEG"
-};
-
-Inst *pc, *prog;
-
-static void
-nextpc(void)
-{
- Inst *new;
-
- new = xmalloc(sizeof(*new));
-
- if (!pc) {
- new->next = NULL;
- prog = new;
- } else {
- new->next = pc->next;
- pc->next = new;
- }
-
- new->prev = pc;
- new->to.kind = NONE;
- new->from.kind = NONE;
- pc = new;
-}
-
-void
-addr(char op, Node *np, Addr *addr)
-{
- switch (addr->kind = np->op) {
- case REG:
- addr->u.reg = np->reg;
- break;
- case CONST:
- addr->u.i = np->sym->u.imm;
- break;
- case AUTO:
- addr->u.i = np->sym->u.v.off;
- break;
- case LABEL:
- case MEM:
- addr->u.sym = np->sym;
- break;
- case INDEX:
- break;
- default:
- abort();
- }
-}
-
-void
-code(uint8_t op, Node *to, Node *from)
-{
-
- nextpc();
- if (from)
- addr(op, from, &pc->from);
- if (to)
- addr(op, to, &pc->to);
- pc->op = op;
-}
-
-void
-inscode(uint8_t op, Addr *to, Addr *from)
-{
- nextpc();
- if (from)
- pc->from = *from;
- if (to)
- pc->to = *to;
- pc->op = op;
-}
-
-void
-delcode(void)
-{
- Inst *prev = pc->prev, *next = pc->next;
-
- free(pc);
- if (!prev) {
- pc = next;
- prog = NULL;
- } else {
- pc = prev;
- prev->next = next;
- if (next)
- next->prev = prev;
- }
-}
-
-void
-writeout(void)
-{
- if (!prog)
- return;
-
- for (pc = prog; pc; pc = pc->next) {
- if (pc->label)
- printf("L%d:", pc->label->id);
- (*instcode[pc->op])();
- }
-}
-
-static void
-addr2txt(uint8_t op, Addr *a)
-{
- Symbol *sym;
-
- switch (a->kind) {
- case REG:
- fputs(regnames[a->u.reg], stdout);
- break;
- case CONST:
- printf("%d", a->u.i);
- break;
- case PAR:
- case AUTO:
- printf("(IX%+d)", a->u.i);
- break;
- case LABEL:
- sym = a->u.sym;
- printf("L%d", sym->id);
- break;
- case INDEX:
- fputs("(HL)", stdout);
- break;
- case MEM:
- sym = a->u.sym;
- if (sym->name)
- printf((op == LDI) ? "%s" : "(%s)", sym->name);
- else
- printf((op == LDI) ? "T%u" : "(T%u)", sym->id);
- break;
- default:
- abort();
- }
-}
-
-static void
-inst0(void)
-{
- printf("\t%s\n", insttext[pc->op]);
-}
-
-static void
-inst1(void)
-{
- uint8_t op = pc->op;
-
- printf("\t%s\t", insttext[op]);
- addr2txt(op, (pc->to.kind != NONE) ? &pc->to : &pc->from);
- putchar('\n');
-}
-
-static void
-inst2(void)
-{
- uint8_t op = pc->op;
-
- printf("\t%s\t", insttext[op]);
- addr2txt(op, &pc->to);
- putchar(',');
- addr2txt(op, &pc->from);
- putchar('\n');
-}
--- a/cc2/generror
+++ /dev/null
@@ -1,19 +1,0 @@
-
-BEGIN {
- print "char *errlist[] = {"
-}
-/^enum nerrors \{/ {
- inhome = 1
-}
-inhome && /E[A-Z]*, / {
- sub(/,/, "", $1)
- printf("\t[%s] = \"", $1)
- for (i = 3; i < NF-1; ++i)
- printf("%s ", $i)
- printf("%s\",\n", $(NF-1));
-}
-inhome && /^}/ {
- print "};"
- inhome = 0
-}
-
--- a/cc2/main.c
+++ /dev/null
@@ -1,56 +1,0 @@
-
-#include <stdarg.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "../inc/cc.h"
-
-#include "cc2.h"
-#include "error.h"
-
-char odebug;
-
-void
-error(unsigned nerror, ...)
-{
- va_list va;
- va_start(va, nerror);
- if (nerror >= ENUMERR)
- fprintf(stderr, "incorrect error number '%d'", nerror);
- else
- vfprintf(stderr, errlist[nerror], va);
- va_end(va);
- putc('\n', stderr);
- exit(1);
-}
-
-bool
-moreinput(void)
-{
- int c;
-
-repeat:
- if (feof(stdin))
- return 0;
- if ((c = getchar()) == '\n' || c == EOF)
- goto repeat;
- ungetc(c, stdin);
- return 1;
-}
-
-int
-main(void)
-{
- fputs("cc2 is not updated with the output of cc1", stderr);
- exit(1);
- while (moreinput()) {
- parse();
- optimize();
- addable();
- generate();
- peephole();
- writeout();
- }
- return 0;
-}
--- a/cc2/optm.c
+++ /dev/null
@@ -1,51 +1,0 @@
-
-#include <stddef.h>
-#include <inttypes.h>
-
-#include "../inc/cc.h"
-#include "cc2.h"
-
-
-#include <stdio.h>
-
-static Node *
-optcasts(Node *np, Type *tp)
-{
- if (!np)
- return NULL;
-
-repeat:
- switch (np->op) {
- case OCAST:
- /* TODO: be careful with the sign */
- if (np->type.flags&INTF && np->type.size >= tp->size) {
- np = np->left;
- goto repeat;
- }
- break;
- case OASSIG:
- tp = &np->type;
- break;
- default:
- if (np->type.size > tp->size)
- np->type = *tp;
- break;
- }
-
- np->left = optcasts(np->left, tp);
- np->right = optcasts(np->right, tp);
- return np;
-}
-
-static Node *
-opt(Node *np)
-{
- np = optcasts(np, &np->type);
- return np;
-}
-
-void
-optimize(void)
-{
- apply(opt);
-}
--- a/cc2/parser.c
+++ /dev/null
@@ -1,603 +1,0 @@
-
-#include <errno.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../inc/cc.h"
-#include "../inc/sizes.h"
-
-#include "cc2.h"
-
-#define MAXLINE 200
-#define NR_STACKSIZ 32
-#define NR_NODEPOOL 128
-#define NR_EXPRESSIONS 64
-
-enum {
- LOCAL, GLOBAL, PARAMETER
-};
-
-Symbol *curfun;
-static Node *stack[NR_STACKSIZ], **stackp;
-static Node *listexp[NR_EXPRESSIONS], **listp;
-static Node nodepool[NR_NODEPOOL], *newp;
-
-
-static Type Funct = {
- .letter = L_FUNCTION,
-};
-
-static Type l_int8 = {
- .letter = L_INT8,
- .size = 1,
- .align = 2,
- .flags = SIGNF | INTF
-};
-
-static Type l_int16 = {
- .letter = L_INT16,
- .size = 2,
- .align = 2,
- .flags = SIGNF | INTF
-
-};
-
-static Type l_int32 = {
- .letter = L_INT32,
- .size = 4,
- .align = 4,
- .flags = SIGNF | INTF
-
-};
-
-static Type l_int64 = {
- .letter = L_INT64,
- .size = 8,
- .align = 8,
- .flags = SIGNF | INTF
-
-};
-
-static Type l_uint8 = {
- .letter = L_UINT8,
- .size = 1,
- .align = 2,
- .flags = INTF
-};
-
-static Type l_uint16 = {
- .letter = L_UINT16,
- .size = 2,
- .align = 2,
- .flags = INTF
-};
-
-static Type l_uint32 = {
- .letter = L_UINT32,
- .size = 4,
- .align = 4,
- .flags = INTF
-};
-
-static Type l_uint64 = {
- .letter = L_UINT64,
- .size = 8,
- .align = 8,
- .flags = INTF
-};
-
-static void cast(char *), operator(char *), assignment(char *), increment(char *),
- globvar(char *), localvar(char *), paramvar(char *), label(char *),
- immediate(char *), unary(char *), oreturn(char *);
-
-/*TODO: Remove hardcoded symbols */
-
-static void (*optbl[])(char *) = {
- [L_INT8] = cast,
- [L_INT16] = cast,
- [L_INT32] = cast,
- [L_INT64] = cast,
- [L_UINT8] = cast,
- [L_UINT16] = cast,
- [L_UINT32] = cast,
- [L_UINT64] = cast,
- [L_BOOL] = cast,
- [L_FLOAT] = cast,
- [L_DOUBLE] = cast,
- [L_LDOUBLE] = cast,
- [L_POINTER] = cast,
- [L_VOID] = cast,
- ['+'] = operator,
- ['%'] = operator,
- ['-'] = operator,
- ['*'] = operator,
- ['/'] = operator,
- ['l'] = operator,
- ['r'] = operator,
- ['&'] = operator,
- ['|'] = operator,
- ['^'] = operator,
- [':'] = assignment,
- [';'] = increment,
- ['Y'] = globvar,
- ['A'] = localvar,
- ['K'] = localvar,
- ['T'] = localvar,
- ['G'] = globvar,
- ['P'] = paramvar,
- ['L'] = label,
- ['#'] = immediate,
- ['@'] = unary,
- ['a'] = unary,
- ['<'] = operator,
- ['>'] = operator,
- [']'] = operator,
- ['['] = operator,
- ['='] = operator,
- ['!'] = unary,
- ['y'] = oreturn,
- ['j'] = NULL,
- ['o'] = operator,
- ['_'] = unary,
- ['~'] = unary,
- [','] = operator,
- ['\177'] = NULL
-};
-
-static void
-prnode(Node *np)
-{
- if (np->left)
- prnode(np->left);
- if (np->right)
- prnode(np->right);
- fprintf(stderr, "\t%c%c", np->op, np->type.letter);
-}
-
-void
-prtree(Node *np)
-{
- prnode(np);
- putc('\n', stderr);
-}
-
-void
-apply(Node *(*fun)(Node *))
-{
- Node **list, *np;
-
- for (list = curfun->u.f.body; np = *list; ++list)
- *list++ = (*fun)(np);
-}
-
-static Symbol *
-parameter(char *num)
-{
- static Symbol tbl[NR_FUNPARAM];
- Symbol *sym;
- unsigned i = atoi(num);
-
- if (!curfun)
- error(ESYNTAX);
- if (i >= NR_FUNPARAM)
- error(EPARNUM);
- sym = &tbl[i];
- sym->id = i;
- return sym;
-}
-
-static Symbol *
-local(char *num)
-{
- static Symbol tbl[NR_INT_IDENT];
- Symbol *sym;
- unsigned i = atoi(num);
-
- if (!curfun)
- error(ESYNTAX);
- if (i >= NR_INT_IDENT)
- error(EINTNUM);
- sym = &tbl[i];
- sym->id = i;
- return sym;
-}
-
-static Symbol *
-global(char *num)
-{
- static Symbol tbl[NR_EXT_IDENT];
- Symbol *sym;
- unsigned i = atoi(num);
-
- if (i >= NR_EXT_IDENT)
- error(EEXTNUM);
-
- sym = &tbl[i];
- sym->id = i;
- return sym;
-}
-
-static Node *
-newnode(void)
-{
- if (newp == &nodepool[NR_NODEPOOL])
- error(ENODEOV);
- return newp++;
-}
-
-Node *
-imm(TINT i)
-{
- Node *np = newnode();
-
- np->op = CONST;
- np->type = l_int16;
- /* FIX: memory leak */
- np->sym = xmalloc(sizeof(Symbol));
- np->sym->u.imm = i;
- np->left = np->right = NULL;
- return np;
-}
-
-static void
-push(Node *np)
-{
- if (stackp == &stack[NR_STACKSIZ])
- error(ESTACKO);
- *stackp++ = np;
-}
-
-static Node *
-pop(void)
-{
- if (stackp == stack)
- error(ESTACKU);
- return *--stackp;
-}
-
-static Type *
-gettype(char *type)
-{
- switch (type[0]) {
- case L_INT8:
- return &l_int8;
- case L_INT16:
- return &l_int16;
- case L_INT32:
- return &l_int32;
- case L_INT64:
- return &l_int64;
- case L_UINT8:
- return &l_uint8;
- case L_UINT16:
- return &l_uint16;
- case L_UINT32:
- return &l_uint32;
- case L_UINT64:
- return &l_uint64;
- case L_FUNCTION:
- return &Funct;
- default:
- error(ETYPERR);
- }
-}
-
-static Symbol *
-symbol(uint8_t t, char *token)
-{
- Symbol *sym;
- static Symbol *(*tbl[3])(char *)= {
- [LOCAL] = local,
- [GLOBAL] = global,
- [PARAMETER] = parameter
- };
- sym = (*tbl[t])(token+1);
- sym->kind = *token;
- return sym;
-}
-
-static void
-variable(uint8_t t, char *token)
-{
- Node *np = newnode();
- Symbol *sym = symbol(t, token);
-
- np->sym = sym;
- np->op = sym->u.v.sclass;
- np->type = sym->u.v.type;
- np->left = np->right = NULL;
- push(np);
-}
-
-static void
-localvar(char *token)
-{
- variable(LOCAL, token);
-}
-
-static void
-globvar(char *token)
-{
- variable(GLOBAL, token);
-}
-
-static void
-paramvar(char *token)
-{
- variable(PARAMETER, token);
-}
-
-static void
-immediate(char *token)
-{
- /* TODO: check type of immediate */
- push(imm(atoi(token+2)));
-}
-
-static void
-unary(char *token)
-{
- Node *np = newnode();
-
- np->right = NULL;
- np->left = pop();
- np->type = *gettype(token+1);
- np->op = token[0];
- push(np);
-}
-
-static void
-operator(char *token)
-{
- Node *np = newnode();
-
- np->right = pop();
- np->left = pop();
- np->type = *gettype(token+1);
- np->op = token[0];
- push(np);
-}
-
-static void
-label(char *token)
-{
- Node *np = newnode();
-
- np->left = np->right = NULL;
- np->op = LABEL;
- np->sym = local(token);
- push(np);
-}
-
-static void
-increment(char *token)
-{
- Node *np = newnode();
-
- np->right = pop();
- np->left = pop();
- np->type = *gettype(token+2);
- np->op = token[0];
- switch (np->subop = token[1]) {
- case '-': case '+':
- push(np);
- break;
- default:
- error(ESYNTAX);
- }
-}
-
-static void
-assignment(char *token)
-{
- Node *np = newnode();
-
- np->right = pop();
- np->left = pop();
- np->op = *token;
- switch (*++token) {
- case OADD: case OSUB: case OINC: case OMOD: case ODIV:
- case OSHL: case OSHR: case OBAND: case OBOR: case OBXOR:
- np->subop = *++token;
- default:
- np->type = *gettype(token);
- break;
- }
- push(np);
-}
-
-static void
-cast(char *token)
-{
- Node *np = newnode();
-
- np->right = NULL;
- np->left = pop();
- np->op = OCAST;
- np->type = *gettype(token+1);
- push(np);
-}
-
-static void
-expr(char *token)
-{
- void (*fun)(char *);
- unsigned c;
-
- do {
- if ((c = token[0]) > 0x7f || (fun = optbl[c]) == NULL)
- error(ESYNTAX);
- (*fun)(token);
- } while (token = strtok(NULL, "\t"));
-}
-
-static void
-expression(char *token)
-{
- Node *np;
-
- if (!curfun)
- error(ESYNTAX);
-
- expr(token);
-
- np = pop();
- if (stackp != stack)
- error(EEXPBAL);
- if (listp == &listexp[NR_EXPRESSIONS])
- error(EEXPROV);
- *listp++ = np;
-}
-
-static void
-oreturn(char *token)
-{
- Node *np = newnode(), *lp;
-
- np->op = token[0];
-
- if (token = strtok(NULL, "\t")) {
- expr(token);
- lp = pop();
- np->left = lp;
- np->type = lp->type;
- } else {
- np->left = NULL;
- }
- np->right = NULL;
- push(np);
-}
-
-static void
-deflabel(char *token)
-{
- Symbol *sym;
-
- if (!curfun)
- error(ESYNTAX);
- sym = local(token);
-}
-
-static Symbol *
-declaration(uint8_t t, char class, char *token)
-{
- Symbol *sym = symbol(t, token);
- char *s;
-
- free(sym->name);
- memset(sym, 0, sizeof(*sym));
- sym->u.v.sclass = class;
-
- if ((s = strtok(NULL, "\t")) == NULL)
- error(ESYNTAX);
- sym->u.v.type = *gettype(s);
- if ((s = strtok(NULL, "\t")) != NULL)
- sym->name = xstrdup(s);
-
- return sym;
-}
-
-static void
-globdcl(char *token)
-{
- Symbol *sym = declaration(GLOBAL, MEM, token);
-
- switch (token[0]) {
- case 'X':
- sym->extrn = 1;
- break;
- case 'G':
- sym->public = 1;
- break;
- }
-
- if (sym->u.v.type.letter != L_FUNCTION)
- return;
-
- if (curfun)
- error(ESYNTAX);
-
- curfun = sym;
- sym->u.f.body = listp = listexp;
- newp = nodepool;
-}
-
-static void
-paramdcl(char *token)
-{
- Symbol *sym = declaration(PARAMETER, AUTO, token);
- sym->u.v.off = -curfun->u.f.params;
- curfun->u.f.params += sym->u.v.type.size;
-}
-
-static void
-localdcl(char *token)
-{
- Symbol *sym = declaration(LOCAL, token[0], token);
- char sclass = *token;
-
- if (sclass == 'A' || sclass == 'R') {
- uint8_t size = sym->u.v.type.size;
- /* stack elements are 2 byte multiple */
- if (size == 1)
- ++size;
- curfun->u.f.locals += size;
- sym->u.v.off = curfun->u.f.locals;
- }
-}
-
-void
-parse(void)
-{
- void (*fun)(char *tok);
- uint8_t len;
- int c;
- char line[MAXLINE];
-
- curfun = NULL;
- stackp = stack;
- listp = listexp;
- newp = nodepool;
-
- for (;;) {
- switch (c = getchar()) {
- case 'L':
- fun = deflabel;
- break;
- case '\t':
- fun = expression;
- break;
- case 'S':
- /* TODO: struct */
- break;
- case 'P':
- fun = paramdcl;
- break;
- case 'A': case 'R': case 'T':
- fun = localdcl;
- break;
- case 'Y': case 'G':
- fun = globdcl;
- break;
- case '}':
- if (curfun)
- return;
- default:
- goto syntax_error;
- }
-
- ungetc(c, stdin);
- if (!fgets(line, sizeof(line), stdin))
- break;
- len = strlen(line);
- if (line[len-1] != '\n')
- error(ELNLINE);
- line[len-1] = '\0';
- (*fun)(strtok(line, "\t"));
- }
-
-syntax_error:
- error(ESYNTAX);
-}
--- a/cc2/peep.c
+++ /dev/null
@@ -1,39 +1,0 @@
-
-#include <inttypes.h>
-#include <stddef.h>
-
-#include "../inc/cc.h"
-#include "cc2.h"
-
-void
-peephole(void)
-{
- Addr to, from;
- TINT i;
- uint8_t op;
-
- for (pc = prog; pc; pc = pc->next) {
- to = pc->to;
- from = pc->from;
-
- switch (pc->op) {
- case SUB:
- case ADD:
- if (from.kind == CONST) {
- if ((i = from.u.i) == 0 || i < 4) {
- delcode();
- op = (pc->op == ADD) ? INC : DEC;
-
- while (i--)
- inscode(op, &to, NULL);
- }
- /* TODO: More optimizations (ex: -1) */
- }
- break;
- case JP:
- if (to.u.sym->u.pc == pc->next)
- delcode();
- break;
- }
- }
-}