scc

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

commit e2fc11a0790f840a9f0f0ce59878f0f0a55fc52d
parent 54f95598858aa76b912be8dc0b980070724f31f2
Author: Roberto E. Vargas Caballero <roberto.vargas@igrid-td.com>
Date:   Wed, 13 Apr 2016 08:48:46 +0200

[cc2-qbe] First implementation of cgen() for qbe

This first version of cgen is the version that is showing
how all the architectures must deal with the asm generation.
In the case of qbe, we are not writing real asm code but
qbe intermediate language.

Diffstat:
cc2/arch/amd64-sysv/cgen.c | 4++--
cc2/arch/i386-sysv/cgen.c | 4++--
cc2/arch/qbe/cgen.c | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
cc2/arch/z80/cgen.c | 4++--
cc2/cc2.h | 11++++++++---
cc2/code.c | 2+-
cc2/main.c | 2+-
cc2/node.c | 7++-----
cc2/symbol.c | 6+++++-
9 files changed, 132 insertions(+), 19 deletions(-)

diff --git a/cc2/arch/amd64-sysv/cgen.c b/cc2/arch/amd64-sysv/cgen.c @@ -2,8 +2,8 @@ #include "arch.h" #include "../../cc2.h" -void -generate(void) +Node * +cgen(Node *np) { } diff --git a/cc2/arch/i386-sysv/cgen.c b/cc2/arch/i386-sysv/cgen.c @@ -2,8 +2,8 @@ #include "arch.h" #include "../../cc2.h" -void -generate(void) +Node * +cgen(Node *np) { } diff --git a/cc2/arch/qbe/cgen.c b/cc2/arch/qbe/cgen.c @@ -1,10 +1,117 @@ +#include <stdlib.h> + #include "arch.h" #include "../../cc2.h" -void -generate(void) +enum sflags { + ISTMP = 1, + ISCONS = 2 +}; + +static Node * +load(Node *np) +{ + Node *new; + Symbol *sym; + + new = newnode(); + sym = getsym(TMPSYM); + sym->type = np->type; + new->u.sym = sym; + new->op = OLOAD; + new->left = np; + new->type = np->type; + new->flags |= ISTMP; + return new; +} + +Node * +cgen(Node *np) { + Node *l, *r; + Symbol *sym; + int op; + + if (!np) + return NULL; + + l = cgen(np->left); + r = cgen(np->right); + + switch (op = np->op) { + case OREG: + case OSTRING: + abort(); + case OCONST: + case OLABEL: + np->flags |= ISCONS; + case OPAR: + case OMEM: + case OAUTO: + return np; + case OADD: + case OSUB: + case OMUL: + case OMOD: + case ODIV: + case OSHL: + case OSHR: + case OLT: + case OGT: + case OLE: + case OGE: + case OEQ: + case ONE: + case OBAND: + case OBOR: + case OBXOR: + case OCPL: + if ((l->flags & (ISTMP|ISCONS)) == 0) + np->left = load(l); + if ((r->flags & (ISTMP|ISCONS)) == 0) + np->right = load(r); + sym = getsym(TMPSYM); + sym->type = np->type; + np->flags |= ISTMP; + np->u.sym = sym; + np->op = OTMP; + code(op, np, np->left, np->right); + return np; + case ONOP: + case OBLOOP: + case OELOOP: + return NULL; + case ONEG: + case OADDR: + case OPTR: + case OCAST: + case OINC: + case ODEC: + abort(); + case OASSIG: + code(op, l, l, r); + return r; + case OCALL: + case OFIELD: + case OCOMMA: + case OASK: + case OCOLON: + case OAND: + case OOR: + abort(); + case OBRANCH: + case OJMP: + code(op, NULL, l, r); + return NULL; + case ORET: + case OCASE: + case ODEFAULT: + case OTABLE: + case OSWITCH: + default: + abort(); + } } /* diff --git a/cc2/arch/z80/cgen.c b/cc2/arch/z80/cgen.c @@ -2,8 +2,8 @@ #include "arch.h" #include "../../cc2.h" -void -generate(void) +Node * +cgen(Node *np) { } diff --git a/cc2/cc2.h b/cc2/cc2.h @@ -39,6 +39,7 @@ enum op { STRING = '"', LABEL = 'L', INDEX = 'I', + OTMP = 'T', /* storage class */ GLOB = 'G', EXTRN = 'X', @@ -51,6 +52,7 @@ enum op { OREG = 'R', OCONST = '#', OSTRING = '"', + OLOAD = 'D', OLABEL = 'L', OADD = '+', OSUB = '-', @@ -81,7 +83,6 @@ enum op { OAND = 'a', OOR = 'o', OPTR = '@', - OSYM = 'i', OCAST = 'g', OINC = 'i', ODEC = 'd', @@ -111,6 +112,7 @@ enum nerrors { ESTACKU, /* stack underflow */ ELNLINE, /* line too long */ EFERROR, /* error reading from file:%s*/ + EBADID, /* incorrect symbol id */ ENUMERR }; @@ -145,6 +147,7 @@ struct node { Type type; char complex; char address; + unsigned char flags; union { TUINT i; char reg; @@ -183,7 +186,7 @@ extern void optimize(void); /* cgen.c */ extern Node *sethi(Node *np); -extern void generate(void); +extern Node *cgen(Node *np); /* peep.c */ extern void peephole(void); @@ -191,6 +194,7 @@ extern void peephole(void); /* code.c */ extern void data(Node *np); extern void writeout(void), endinit(void), newfun(void); +extern void code(int op, Node *to, Node *from1, Node *from2); extern void defvar(Symbol *), defpar(Symbol *), defglobal(Symbol *); /* node.c */ @@ -202,7 +206,8 @@ extern Node *newnode(void); extern Symbol *curfun; /* symbol.c */ -extern Symbol *getsym(int id); +#define TMPSYM 0 +extern Symbol *getsym(unsigned id); extern void popctx(void); extern void pushctx(void); extern void freesym(Symbol *sym); diff --git a/cc2/code.c b/cc2/code.c @@ -26,7 +26,7 @@ nextpc(void) pc = new; } -void +static void addr(int op, Node *np, Addr *addr) { switch (addr->kind = np->op) { diff --git a/cc2/main.c b/cc2/main.c @@ -40,7 +40,7 @@ main(void) parse(); optimize(); apply(sethi); - generate(); + apply(cgen); peephole(); writeout(); } diff --git a/cc2/node.c b/cc2/node.c @@ -1,5 +1,6 @@ #include <stdlib.h> +#include <string.h> #include "../inc/cc.h" @@ -39,11 +40,7 @@ newnode(void) np = freep; freep = np->left; - np->right = NULL; - np->left = NULL; - np->stmt = NULL; - np->label = NULL; - return np; + return memset(np, 0, sizeof(np)); } void diff --git a/cc2/symbol.c b/cc2/symbol.c @@ -1,4 +1,5 @@ +#include <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -43,10 +44,13 @@ popctx(void) } Symbol * -getsym(int id) +getsym(unsigned id) { Symbol **htab, *sym; + if (id > USHRT_MAX) + error(EBADID); + htab = &symtab[id & NR_SYMHASH-1]; for (sym = *htab; sym; sym = sym->h_next) { if (sym->id > 0 && sym->id == id)