ref: 48fa7fb8560c55dda4fdb5446568a359aad6b892
parent: d34385129759c3dee491244cde354859450efa81
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Wed Apr 13 04:48:46 EDT 2016
[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.
--- 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)
{
}
--- 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)
{
}
--- 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();
+ }
}
/*
--- 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)
{
}
--- a/cc2/cc2.h
+++ b/cc2/cc2.h
@@ -39,6 +39,7 @@
STRING = '"',
LABEL = 'L',
INDEX = 'I',
+ OTMP = 'T',
/* storage class */
GLOB = 'G',
EXTRN = 'X',
@@ -51,6 +52,7 @@
OREG = 'R',
OCONST = '#',
OSTRING = '"',
+ OLOAD = 'D',
OLABEL = 'L',
OADD = '+',
OSUB = '-',
@@ -81,7 +83,6 @@
OAND = 'a',
OOR = 'o',
OPTR = '@',
- OSYM = 'i',
OCAST = 'g',
OINC = 'i',
ODEC = 'd',
@@ -111,6 +112,7 @@
ESTACKU, /* stack underflow */
ELNLINE, /* line too long */
EFERROR, /* error reading from file:%s*/
+ EBADID, /* incorrect symbol id */
ENUMERR
};
@@ -145,6 +147,7 @@
Type type;
char complex;
char address;
+ unsigned char flags;
union {
TUINT i;
char reg;
@@ -183,7 +186,7 @@
/* 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 @@
/* 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 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);
--- a/cc2/code.c
+++ b/cc2/code.c
@@ -26,7 +26,7 @@
pc = new;
}
-void
+static void
addr(int op, Node *np, Addr *addr)
{
switch (addr->kind = np->op) {
--- a/cc2/main.c
+++ b/cc2/main.c
@@ -40,7 +40,7 @@
parse();
optimize();
apply(sethi);
- generate();
+ apply(cgen);
peephole();
writeout();
}
--- 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 @@
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
--- 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,9 +44,12 @@
}
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) {
--
⑨