scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

commit 827b4cdaa90cabaa1ee149a79ceb4cf7c7813f47
parent 9a2913311bd77d7075a327854a725d03eff554a2
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed, 20 Jan 2016 20:11:09 +0100

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.

Diffstat:
cc2.old/Makefile | 23+++++++++++++++++++++++
cc2.old/cast.patch | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cc2.old/cc2.h | 179+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cc2.old/cgen.c | 602+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cc2.old/code.c | 229+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cc2.old/generror | 19+++++++++++++++++++
cc2.old/main.c | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cc2.old/optm.c | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
cc2.old/parser.c | 603+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cc2.old/peep.c | 39+++++++++++++++++++++++++++++++++++++++
cc2/Makefile | 23-----------------------
cc2/cc2.h | 179-------------------------------------------------------------------------------
cc2/cgen.c | 602-------------------------------------------------------------------------------
cc2/code.c | 229-------------------------------------------------------------------------------
cc2/generror | 19-------------------
cc2/main.c | 56--------------------------------------------------------
cc2/optm.c | 51---------------------------------------------------
cc2/parser.c | 603-------------------------------------------------------------------------------
cc2/peep.c | 39---------------------------------------
19 files changed, 1862 insertions(+), 1801 deletions(-)

diff --git a/cc2.old/Makefile b/cc2.old/Makefile @@ -0,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 + diff --git a/cc2.old/cast.patch b/cc2.old/cast.patch @@ -0,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 *) = { diff --git a/cc2.old/cc2.h b/cc2.old/cc2.h @@ -0,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); diff --git a/cc2.old/cgen.c b/cc2.old/cgen.c @@ -0,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 = &regs[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 = &regs[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, &regs[lower[reg]], np); + code(LDH, &regs[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, &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 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, &regs[IX]); + code(MOV, &regs[IX], &regs[SP]); + if (size > 6) { + code(MOV, &regs[HL], imm(-size)); + code(ADD, &regs[HL], &regs[SP]); + code(MOV, &regs[SP], &regs[HL]); + } else { + for (; size != 0; size-= 2) + code(PUSH, NULL, &regs[HL]); + } + + for (stmt = curfun->u.f.body; np = *stmt; ++stmt) + cgen(np); + + code(MOV, &regs[SP], &regs[IX]); + retlabel.u.pc = pc; + pc->label = &retlabel; + code(POP, &regs[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); +} diff --git a/cc2.old/code.c b/cc2.old/code.c @@ -0,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'); +} diff --git a/cc2.old/generror b/cc2.old/generror @@ -0,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 +} + diff --git a/cc2.old/main.c b/cc2.old/main.c @@ -0,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; +} diff --git a/cc2.old/optm.c b/cc2.old/optm.c @@ -0,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); +} diff --git a/cc2.old/parser.c b/cc2.old/parser.c @@ -0,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); +} diff --git a/cc2.old/peep.c b/cc2.old/peep.c @@ -0,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; + } + } +} diff --git a/cc2/Makefile b/cc2/Makefile @@ -1,23 +0,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 - diff --git a/cc2/cc2.h b/cc2/cc2.h @@ -1,179 +0,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); diff --git a/cc2/cgen.c b/cc2/cgen.c @@ -1,602 +0,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 = &regs[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 = &regs[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, &regs[lower[reg]], np); - code(LDH, &regs[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, &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 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, &regs[IX]); - code(MOV, &regs[IX], &regs[SP]); - if (size > 6) { - code(MOV, &regs[HL], imm(-size)); - code(ADD, &regs[HL], &regs[SP]); - code(MOV, &regs[SP], &regs[HL]); - } else { - for (; size != 0; size-= 2) - code(PUSH, NULL, &regs[HL]); - } - - for (stmt = curfun->u.f.body; np = *stmt; ++stmt) - cgen(np); - - code(MOV, &regs[SP], &regs[IX]); - retlabel.u.pc = pc; - pc->label = &retlabel; - code(POP, &regs[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); -} diff --git a/cc2/code.c b/cc2/code.c @@ -1,229 +0,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'); -} diff --git a/cc2/generror b/cc2/generror @@ -1,19 +0,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 -} - diff --git a/cc2/main.c b/cc2/main.c @@ -1,56 +0,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; -} diff --git a/cc2/optm.c b/cc2/optm.c @@ -1,51 +0,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); -} diff --git a/cc2/parser.c b/cc2/parser.c @@ -1,603 +0,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); -} diff --git a/cc2/peep.c b/cc2/peep.c @@ -1,39 +0,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; - } - } -}