scc

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

commit 169c191fd3a86d22ae6847311dcd82a6483a4aa9
parent 00612b9bd60706d7e77d3bbc165aa13e2a91556d
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Fri, 13 Mar 2015 20:39:33 +0000

Rewrite cc2 to store asm instructions in memory

We want to do some optimizations in the code, so it is good idea
to stroe them in memory so we will be able to operate in it later.
This is only an initial commit, but it will be the base for future work.

Diffstat:
Mcc2/cc2.h | 92++++++++++++++++++++++++++++++++++++++++++++-----------------------------------
Mcc2/cgen.c | 118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Mcc2/code.c | 158++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Mcc2/main.c | 1+
Mcc2/optm.c | 2+-
Mcc2/parser.c | 20+++++++++++++-------
6 files changed, 285 insertions(+), 106 deletions(-)

diff --git a/cc2/cc2.h b/cc2/cc2.h @@ -2,6 +2,45 @@ #define SIGNF 1 #define INTF 2 +#define NONE 0 +#define FUN 0 +#define VAR 1 +#define EFUN 2 +#define AUTO 'A' +#define REG 'R' +#define MEM 'T' +#define PAR 'P' +#define CONST '#' +#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 ADDABLE 10 + + typedef struct symbol Symbol; typedef struct node Node; @@ -40,10 +79,12 @@ struct node { Type type; uint8_t complex; uint8_t addable; + uint8_t kind; union { Symbol *sym; + /* TODO: Admit inmediate of other type */ TINT imm; - char reg; + uint8_t reg; } u; struct node *left, *right; }; @@ -64,60 +105,29 @@ enum nerrors { ENUMERR }; -#define FUN 0 -#define VAR 1 -#define EFUN 2 -#define AUTO 'A' -#define REG 'R' -#define MEM 'T' -#define PAR 'P' -#define CONST '#' -#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 ADDABLE 10 enum { - PUSH, POP, LD, ADD, RET, ADDI, LDI, ADDX, ADCX, LDX, - LDFX + LDW, LDL, LDH, MOV, ADD, PUSH, POP, RET, NOP }; enum { A = 1, B, C, D, E, H, L, IYL, IYH, NREGS, - IXL, IXH, F, I, SP, AF, HL, DE, BC, IX, IY + SP = NREGS, AF, HL, DE, BC, IX, IY }; +extern Type Funct, l_int8, l_int16, l_int32, l_int64, + l_uint8, l_uint16, l_uint32, l_uint64; + +/*TODO: separate functions for file */ extern void error(unsigned nerror, ...); extern Node *genaddable(Node *np); extern void generate(Symbol *fun); extern void genstack(Symbol *fun); extern void apply(Node *list[], Node *(*fun)(Node *)); extern Symbol *parse(void); -extern void code(char op, ...); +extern void code(uint8_t op, Node *to, Node *from); extern Node *optimize(Node *np); extern void prtree(Node *np); +extern Node *imm(TINT i, Type *tp); +extern void writeout(void); diff --git a/cc2/cgen.c b/cc2/cgen.c @@ -7,18 +7,88 @@ #include "../inc/cc.h" #include "cc2.h" -#include <stdio.h> static bool reguse[NREGS]; -static char upper[] = {[DE] = D, [HL] = H, [BC] = B, [IX] = IXH, [IY] = IYH}; -static char lower[] = {[DE] = E, [HL] = L, [BC] = C, [IX] = IXL, [IY] = IYL}; +static char upper[] = {[DE] = D, [HL] = H, [BC] = B, [IY] = IYH}; +static char lower[] = {[DE] = E, [HL] = L, [BC] = C, [IY] = IYL}; +Node +reg_E = { + .op = REG, + .u.reg = E +}, +reg_D = { + .op = REG, + .u.reg = D +}, +reg_H = { + .op = REG, + .u.reg = H +}, +reg_L = { + .op = REG, + .u.reg = L +}, +reg_C = { + .op= REG, + .u.reg = C +}, +reg_B = { + .op= REG, + .u.reg = B +}, +reg_A = { + .op= REG, + .u.reg = A +}, +reg_IYL = { + .op = REG, + .u.reg = IYL +}, +reg_IYH = { + .op = REG, + .u.reg = IYH +}, +reg_DE = { + .op = REG, + .u.reg = DE +}, +reg_HL = { + .op = REG, + .u.reg = HL +}, +reg_BC = { + .op = REG, + .u.reg = BC +}, +reg_IX = { + .op = REG, + .u.reg = IX +}, +reg_IY = { + .op = REG, + .u.reg = IY +}, +reg_SP = { + .op = REG, + .u.reg = SP +}; + +Node *regs[] = { + [A] = &reg_A, + [B] = &reg_B, [C] = &reg_C, + [D] = &reg_D, [E] = &reg_E, + [H] = &reg_H, [L] = &reg_L, + [IYL] = &reg_IYL, [IYH] = &reg_IYH, + [HL] = &reg_HL, [DE] = &reg_DE, [BC]= &reg_BC, + [IX] = &reg_IX, [IY] = &reg_IY, [SP] = &reg_SP +}; static char allocreg(Node *np) { - char reg8[] = {A, B, C, D, E, H, L, IYL, IY, 0}; - char reg16[] = {BC, HL, DE, IY, 0}; + static char reg8[] = {A, B, C, D, E, H, L, IYL, IY, 0}; + static char reg16[] = {BC, HL, DE, IY, 0}; char *bp, c; switch (np->type.size) { @@ -60,11 +130,11 @@ move(Node *np) sym = np->u.sym; switch (np->type.size) { case 1: - code(LDFX, reg, IX, sym->u.v.off); + code(LDL, regs[reg], np); break; case 2: - code(LDFX, lower[reg], IX, sym->u.v.off); - code(LDFX, upper[reg], IX, sym->u.v.off+1); + code(LDL, regs[lower[reg]], np); + code(LDH, regs[upper[reg]], np); break; case 4: case 8: @@ -133,10 +203,10 @@ cgen(Node *np, Node *parent) rp = np->right; } else if (lp->u.reg != A) { /* TODO: Move A to variable */ - code(PUSH, AF); - code(LD, A, lp->u.reg); + code(PUSH, NULL, lp); + code(LDL, regs[A], lp); } - code(ADD, A, rp->u.reg); + code(ADD, regs[A], rp); np->op = REG; np->u.reg = A; break; @@ -147,11 +217,11 @@ cgen(Node *np, Node *parent) rp = np->right; } else if (lp->u.reg != HL && lp->u.reg != IY) { /* TODO: Move HL to variable */ - code(PUSH, HL); - code(LD, H, upper[lp->u.reg]); - code(LD, L, lower[lp->u.reg]); + code(PUSH, NULL, lp); + code(LDL, regs[L], lp); + code(LDH, regs[H], lp); } - code(ADD, lp->u.reg, rp->u.reg); + code(ADD, lp, rp); np->op = REG; np->u.reg = lp->u.reg; break; @@ -165,7 +235,7 @@ cgen(Node *np, Node *parent) case 1: switch (lp->op) { case AUTO: - code(LDX, IX, lp->u.sym->u.v.off, rp->u.reg); + code(LDL, rp, lp); break; case REG: case MEM: @@ -196,19 +266,19 @@ generate(Symbol *fun) char frame = fun->u.f.locals != 0 || odebug; if (frame) { - code(PUSH, IX); - code(LD, IX, SP); - code(LDI, HL, -fun->u.f.locals); - code(ADD, HL, SP); - code(LD, SP, HL); + code(PUSH, NULL, regs[IX]); + code(MOV, regs[IX], regs[SP]); + code(MOV, regs[HL], imm(-fun->u.f.locals, &l_int16)); + code(ADD, regs[HL], regs[SP]); + code(MOV, regs[SP], regs[HL]); } apply(fun->u.f.body, applycgen); if (frame) { - code(LD, SP, IX); - code(POP, IX); - code(RET); + code(MOV, regs[SP], regs[IX]); + code(POP, regs[IX], NULL); + code(RET, NULL, NULL); } } diff --git a/cc2/code.c b/cc2/code.c @@ -1,19 +1,57 @@ #include <stdarg.h> -#include <stddef.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, + [MOV] = inst2, + [ADD] = inst2, + [PUSH] = inst1, + [POP] = inst1, + [RET] = inst0, + [NOP] = inst0 +}; + +static char *insttext[] = { + [LDW] = "LD", + [LDL] = "LD", + [LDH] = "LD", + [MOV] = "LD", + [ADD] = "ADD", + [PUSH] = "PUSH", + [POP] = "POP", + [RET] = "RET", + [NOP] = "NOP" +}; + typedef struct inst Inst; typedef struct addr Addr; struct addr { char kind; union { - char reg; + uint8_t reg; + TINT i; Inst *pc; Symbol *sym; } u; @@ -24,38 +62,10 @@ struct inst { Addr from, to; Inst *next; }; - -static char *opnames[] = { - [PUSH] = "PUSH", [POP] = "POP", [LD] = "LD", [ADD] = "ADD", - [RET] = "RET" , [ADDI]= "ADD", [LDI] = "LD", [ADDX] = "ADD", - [ADCX] = "ADC" , [LDX] = "LD" , [LDFX] = "LD" -}; - -static char *regnames[] = { - [AF] = "AF", [HL] = "HL", [DE] = "DE", [BC] = "BC", [IX] = "IX", - [IY] = "IY", [SP] = "SP", [A] = "A", [F] = "F", [B] = "B", - [C] = "C", [D] = "D", [E] = "E", [H] = "H", [L] = "L", - [IXL]= "IXL",[IXH]= "IXH",[IYL]= "IYL",[IYH]= "IYH", [I] = "I" -}; - -static char *opfmt[] = { - [RET] = "\to", - [PUSH] = "\to\tr", - [POP] = "\to\tr", - [ADD] = "\to\tr,r", - [LD] = "\to\tr,r", - [ADDI] = "\to\tr,i", - [LDI] = "\to\tr,i", - [ADDX] = "\to\tr,(r+i)", - [ADCX] = "\to\tr,(r+i)", - [LDFX] = "\to\tr,(r+i)", - [LDX] = "\to\t(r+i),r", -}; - Inst *prog, *pc; Inst * -inst(uint8_t op) +nextpc(void) { Inst *new; @@ -65,12 +75,94 @@ inst(uint8_t op) else pc->next = new; pc = new; - pc->op = op; + pc->op = NOP; + pc->to.kind = NONE; + pc->from.kind = NONE; pc->next = NULL; return pc; } void -code(char op, ...) +addr(char op, Node *np, Addr *addr) +{ + switch (addr->kind = np->op) { + case REG: + addr->u.reg = np->u.reg; + break; + case CONST: + addr->u.i = np->u.imm; + break; + case AUTO: + addr->u.i = np->u.sym->u.v.off; + break; + default: + abort(); + } +} + +void +code(uint8_t op, Node *to, Node *from) +{ + Inst *ip; + + ip = nextpc(); + if (from) + addr(op, from, &ip->from); + if (to) + addr(op, to, &ip->to); + ip->op = op; +} + +void +writeout(void) +{ + if (!prog) + return; + + for (pc = prog; pc; pc = pc->next) + (*instcode[pc->op])(); +} + +static void +addr2txt(Addr *a) +{ + switch (a->kind) { + case REG: + fputs(regnames[a->u.reg], stdout); + break; + case CONST: + printf("%d", a->u.i); + break; + case AUTO: + printf("(IX+%d)", a->u.i); + break; + case MEM: + case PAR: + default: + abort(); + } +} + +static void +inst0(void) +{ + printf("\t%s\n", insttext[pc->op]); +} + +static void +inst1(void) +{ + printf("\t%s\t", insttext[pc->op]); + addr2txt((pc->to.kind != NONE) ? &pc->to : &pc->from); + putchar('\n'); +} + +static void +inst2(void) { + printf("\t%s\t", insttext[pc->op]); + addr2txt(&pc->to); + putchar(','); + addr2txt(&pc->from); + putchar('\n'); } diff --git a/cc2/main.c b/cc2/main.c @@ -34,5 +34,6 @@ main(void) apply(fun->u.f.body, optimize); apply(fun->u.f.body, genaddable); generate(fun); + writeout(); } } diff --git a/cc2/optm.c b/cc2/optm.c @@ -18,7 +18,7 @@ repeat: switch (np->op) { case OCAST: /* TODO: be careful with the sign */ - if (np->type.flags & INTF && np->type.size >= tp->size) { + if (np->type.flags&INTF && np->type.size >= tp->size) { np = np->left; goto repeat; } diff --git a/cc2/parser.c b/cc2/parser.c @@ -161,6 +161,18 @@ newnode(void) return newp++; } + +Node * +imm(TINT i, Type *tp) +{ + Node *np = newnode(); + + np->op = CONST; + np->type = *tp; + np->u.imm = i; + np->left = np->right = NULL; +} + static void push(Node *np) { @@ -249,13 +261,7 @@ paramvar(char *token) static void immediate(char *token) { - Node *np = newnode(); - - np->op = CONST; - np->type = *gettype(token+1); - np->u.imm = atoi(token+2); - np->left = np->right = NULL; - push(np); + push(imm(atoi(token+2), gettype(token+1))); } static void