commit 79059d14d5c6a36a81e74697aabdab5901c59b5c
parent 828528f9e6b85837d6b804aac5cbc18f97116bfb
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Sun, 15 Feb 2015 19:40:01 +0100
Merge remote-tracking branch 'gitorius/master'
Diffstat:
M | cc1/cc1.h | | | 67 | +++++++++++++++++++++++++++++++------------------------------------ |
M | cc1/code.c | | | 60 | ++++++++++++++++++++++++++++++++++++++++++++++-------------- |
M | cc1/decl.c | | | 322 | +++++++++++++++++++++++++++++++++++++++---------------------------------------- |
M | cc1/expr.c | | | 68 | ++++++++++++++++++++++++++++++++------------------------------------ |
M | cc1/lex.c | | | 5 | +++-- |
M | cc1/stmt.c | | | 63 | +++++++++++++++++++++++++++++++++++++++++++-------------------- |
M | cc1/symbol.c | | | 32 | ++++++++++++++------------------ |
M | cc1/types.c | | | 157 | ++++++++++++++++++++++++++++++------------------------------------------------- |
M | cc2/Makefile | | | 2 | +- |
M | cc2/cc2.h | | | 33 | +++++++++++++++++++++++++++------ |
M | cc2/cgen.c | | | 188 | ++++++++++++++++++++++++++++--------------------------------------------------- |
A | cc2/code.c | | | 69 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | cc2/main.c | | | 10 | +++++++--- |
A | cc2/optm.c | | | 43 | +++++++++++++++++++++++++++++++++++++++++++ |
M | cc2/parser.c | | | 79 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------- |
15 files changed, 655 insertions(+), 543 deletions(-)
diff --git a/cc1/cc1.h b/cc1/cc1.h
@@ -26,37 +26,26 @@ enum {
NS_IDEN = 0,
NS_TAG,
NS_LABEL,
+ NS_STRUCTS,
NR_NAMESPACES
};
typedef struct ctype Type;
typedef struct symbol Symbol;
-typedef struct field {
- char *name;
- Type *type;
- int id;
- struct field *next;
-} Field;
-
-typedef struct funpar {
- Type *type;
- struct funpar *next;
-} Funpar;
-
struct ctype {
uint8_t op; /* type builder operator */
+ uint8_t ns;
char letter; /* letter of the type */
- bool defined : 1; /* type defined (is not a forward reference) */
- bool sign : 1; /* sign type */
+ bool defined : 1; /* type defined (is not a forward reference) */
+ bool sign : 1; /* sign type */
struct ctype *type; /* base type */
struct ctype *next; /* next element in the hash */
- union typeval {
- unsigned char rank; /* convertion rank */
- short nelem; /* number of elements in arrays */
- struct funpar *pars; /* function parameters */
- Field *fields; /* aggregate fields */
- } u;
+ Type **pars; /* type parameters */
+ union {
+ unsigned char rank; /* convertion rank */
+ short elem; /* number of type parameters */
+ } n;
};
@@ -67,18 +56,18 @@ struct symbol {
Type *type;
short id;
uint8_t ctx;
+ uint8_t ns;
uint8_t token;
- struct {
- bool isglobal : 1;
- bool isstatic : 1;
- bool isauto : 1;
- bool isregister : 1;
- bool isdefined : 1;
- } s;
+ bool isglobal : 1;
+ bool isstatic : 1;
+ bool isauto : 1;
+ bool isregister : 1;
+ bool isdefined : 1;
+ bool isfield : 1;
+ bool isparameter : 1;
union {
int i;
char *s;
- struct symbol *sym;
uint8_t token;
} u;
struct symbol *next;
@@ -87,17 +76,17 @@ struct symbol {
extern bool eqtype(Type *tp1, Type *tp2);
extern Type *ctype(int8_t type, int8_t sign, int8_t size),
- *mktype(Type *tp, uint8_t op, void *data);
+ *mktype(Type *tp, uint8_t op, short nelem, void *data);
extern Symbol
*lookup(char *s, unsigned char ns),
*install(char *s, unsigned char ns);
+extern void pushctx(void), popctx(void);
+
typedef struct caselist Caselist;
extern void compound(Symbol *lbreak, Symbol *lcont, Caselist *lswitch);
-extern Type *aggregate(Type *(*fun)(void));
-extern void context(Symbol *lbreak, Symbol *lcont, Caselist *lswitch);
extern Type *typename(void);
@@ -157,6 +146,7 @@ typedef struct node {
void (*code)(struct node *);
Type *type;
uint8_t typeop;
+ uint8_t nchilds;
struct {
bool lvalue : 1;
bool symbol: 1;
@@ -166,7 +156,6 @@ typedef struct node {
Symbol *sym;
Type *type;
char op;
- Field *field;
} u;
struct node *childs[];
} Node;
@@ -178,11 +167,13 @@ enum {
OA_MOD, OA_ADD, OA_SUB, OA_SHL, OA_SHR,
OA_AND, OA_XOR, OA_OR, OADDR,ONEG, OCPL, OEXC,
OCOMMA,
+ /* TODO: This order is important, but must be changed */
+ OAND, OOR,
/*
* Complementary relational operators only differ in less
* significant bit
*/
- OEQ = 0x40, ONE, OLT, OGE, OLE, OGT, OAND, OOR
+ OEQ = 0x40, ONE, OLT, OGE, OLE, OGT
};
extern void
@@ -194,7 +185,8 @@ extern void
emitswitch(short, Node *), emitcase(Symbol *, Node *),
emitret(Type *tp),
emitfun(Symbol *sym),
- emitdefault(Symbol *);
+ emitdefault(Symbol *),
+ emitstruct(Symbol *sym), emitestruct(void);
extern Node
*node(void (*code)(Node *),
@@ -205,12 +197,15 @@ extern Node
*sizeofcode(Type *tp),
*ternarycode(Node *cond, Node *ifyes, Node *ifno),
*symcode(Symbol *sym),
- *fieldcode(Node *child, struct field *fp);
+ *fieldcode(Node *child, Symbol *field);
+
+extern void freetree(Node *np);
#define NEGATE(n, v) ((n)->u.op ^= (v))
/* TODO: remove some of these ugly macros */
#define ISNODEBIN(n) ((n)->code == emitbin)
-#define ISNODECMP(n) (ISNODEBIN(n) && (n)->u.op & 0x40)
+#define ISNODECMP(n) (ISNODEBIN(n) && (n)->u.op >= OEQ)
+#define ISNODELOG(n) (ISNODEBIN(n) && (n)->u.op >= OAND)
extern Node *expr(void);
extern void extdecl(void), decl(void);
diff --git a/cc1/code.c b/cc1/code.c
@@ -1,6 +1,7 @@
#include <stdint.h>
#include <stdio.h>
+#include <stdlib.h>
#include <cc.h>
#include "cc1.h"
@@ -58,25 +59,43 @@ node(void (*code)(Node *), Type *tp, union unode u, uint8_t nchilds)
np->code = code;
np->type = tp;
np->typeop = tp->op;
+ np->nchilds = nchilds;
np->u = u;
np->b.symbol = np->b.lvalue = 0;
return np;
}
+void
+freetree(Node *np)
+{
+ Node **p;
+
+ if (!np)
+ return;
+
+ for (p = np->childs; np->nchilds--; ++p)
+ freetree(*p);
+ free(np);
+}
+
static void
-emitsym2(Symbol *sym)
+emitvar(Symbol *sym)
{
char c;
- if (sym->s.isstatic && !sym->s.isglobal)
+ if (sym->isstatic && !sym->isglobal)
c = 'T';
- else if (sym->s.isstatic && sym->s.isglobal)
+ else if (sym->isstatic && sym->isglobal)
c = 'Y';
- else if (sym->s.isglobal)
+ else if (sym->isglobal)
c = 'G';
- else if (sym->s.isregister)
- c = 'Q';
+ else if (sym->isregister)
+ c = 'R';
+ else if (sym->isfield)
+ c = 'M';
+ else if (sym->isparameter)
+ c = 'P';
else
c = 'A';
printf("%c%d", c, sym->id);
@@ -98,10 +117,22 @@ emitconst(Node *np)
}
void
+emitstruct(Symbol *sym)
+{
+ printf("S%d\t(\n", sym->id);
+}
+
+void
+emitestruct(void)
+{
+ puts(")");
+}
+
+void
emitsym(Node *np)
{
putchar('\t');
- (np->b.constant) ? emitconst(np) : emitsym2(np->u.sym);
+ (np->b.constant) ? emitconst(np) : emitvar(np->u.sym);
}
static void
@@ -113,7 +144,7 @@ emittype(Type *tp)
void
emitdcl(Symbol *sym)
{
- emitsym2(sym);
+ emitvar(sym);
putchar('\t');
emittype(sym->type);
putchar('\n');
@@ -185,13 +216,14 @@ emitprint(Node *np)
{
(*np->code)(np);
printf("\tk%c\n", np->type->letter);
+ fflush(stdout);
}
void
emitfun(Symbol *sym)
{
printf("%c%d\tF\t%s\t{\n",
- sym->s.isglobal ? 'G' : 'Y', sym->id, sym->name);
+ sym->isglobal ? 'G' : 'Y', sym->id, sym->name);
}
void
@@ -264,14 +296,14 @@ emitfield(Node *np)
child = np->childs[0];
(*child->code)(child);
-
- printf("\tM%d", np->u.field->id);
+ putchar('\t');
+ emitvar(np->u.sym);
}
Node *
-fieldcode(Node *child, struct field *fp)
+fieldcode(Node *child, Symbol *field)
{
- Node *np = node(emitfield, fp->type, FIELD(fp), 1);
+ Node *np = node(emitfield, field->type, SYM(field), 1);
np->childs[0] = child;
return np;
}
@@ -284,7 +316,7 @@ castcode(Node *child, Type *tp)
np->childs[0] = child;
return np;
}
-
+
Node *
unarycode(char op, Type *tp, Node *child)
{
diff --git a/cc1/decl.c b/cc1/decl.c
@@ -15,20 +15,18 @@
struct dcldata {
uint8_t op;
- union dclunion {
- unsigned short nelem;
- Symbol *sym;
- Funpar *pars;
- } u;
+ unsigned short nelem;
+ void *data;
};
static struct dcldata *
-queue(struct dcldata *dp, uint8_t op, union dclunion u)
+queue(struct dcldata *dp, uint8_t op, short nelem, void *data)
{
if (dp->op == 255)
error("too much declarators");
dp->op = op;
- dp->u = u;
+ dp->nelem = nelem;
+ dp->data = data;
return dp + 1;
}
@@ -37,78 +35,88 @@ arydcl(struct dcldata *dp)
{
expect('[');
expect(']');
- return queue(dp, ARY, (union dclunion) {.nelem = 0});
+ return queue(dp, ARY, 0, NULL);
}
-static Type *parameter(void);
+static Symbol *parameter(void);
static struct dcldata *
fundcl(struct dcldata *dp)
{
- uint8_t n = 0;
- Funpar *fp;
+ size_t siz;
+ uint8_t n, i, noname;
+ Type *pars[NR_FUNPARAM], **tp = pars;
+ Symbol *syms[NR_FUNPARAM], **sp = syms, *sym;
+ pushctx();
expect('(');
+ n = noname = 0;
do {
- Type *tp;
-
- if ((tp = parameter()) == voidtype) {
+ if ((sym = parameter()) == NULL) {
if (n == 0)
break;
- else
- error("incorrect void parameter");
+ error("incorrect void parameter");
}
- /* TODO: Use an array and allocate memory at the end */
- fp = xmalloc(sizeof(*fp));
- fp->type = tp;
- fp->next = NULL;
- if (!dp->u.pars) {
- dp->u.pars = fp;
- } else {
- register Funpar *p, *q;
-
- for (p = dp->u.pars; q = p->next; p = q)
- /* nothing */;
- p->next = fp;
- }
- ++n;
+ if (n++ == NR_FUNPARAM)
+ error("too much parameters in function definition");
+ *sp++ = sym;
+ *tp++ = sym->type;
+ noname |= sym->name[0] == '\0';
} while (accept(','));
-ret:
- expect(')');;
- return queue(dp, FTN, (union dclunion) {.pars = fp});
+ expect(')');
+ if (n != 0) {
+ siz = sizeof(*tp) * n;
+ tp = memcpy(xmalloc(siz), pars, siz);
+ } else {
+ tp = NULL;
+ }
+
+ if (yytoken != '{') {
+ /* it is only a prototype */
+ popctx();
+ } else {
+ /* it is a function definition */
+ if (noname)
+ error("parameter name omitted");
+ sp = syms;
+ for (i = 0; i < n; ++i)
+ emitdcl(*sp++);
+ }
+
+ return queue(dp, FTN, n, tp);
}
static Symbol *
-newiden(void)
+newiden(uint8_t ns)
{
Symbol *sym;
extern uint8_t curctx;
- if (yylval.sym && yylval.sym->ctx == curctx)
+ if (yylval.sym && yylval.sym->ctx == curctx && yylval.sym->ns == ns)
error("redeclaration of '%s'", yytext);
- sym = install(yytext, NS_IDEN);
+ sym = install(yytext, ns);
next();
return sym;
}
-static struct dcldata *declarator0(struct dcldata *dp);
+static struct dcldata *declarator0(struct dcldata *dp, uint8_t ns);
static struct dcldata *
-directdcl(struct dcldata *dp)
+directdcl(struct dcldata *dp, uint8_t ns)
{
register Symbol *sym;
if (accept('(')) {
- dp = declarator0(dp);
+ dp = declarator0(dp, ns);
expect(')');
} else {
if (yytoken == IDEN || yytoken == TYPEIDEN)
- sym = newiden();
+ sym = newiden(ns);
else
- sym = install("", NS_IDEN);
- dp = queue(dp, IDEN, (union dclunion) {.sym = sym});
+ sym = install("", ns);
+ dp = queue(dp, IDEN, 0, sym);
}
for (;;) {
@@ -121,7 +129,7 @@ directdcl(struct dcldata *dp)
}
static struct dcldata*
-declarator0(struct dcldata *dp)
+declarator0(struct dcldata *dp, uint8_t ns)
{
register uint8_t n;
@@ -130,16 +138,16 @@ declarator0(struct dcldata *dp)
/* nothing */;
}
- dp = directdcl(dp);
+ dp = directdcl(dp, ns);
while (n--)
- dp = queue(dp, PTR, (union dclunion) {});
+ dp = queue(dp, PTR, 0, NULL);
return dp;
}
static Symbol *
-declarator(Type *tp, int8_t flags)
+declarator(Type *tp, int8_t flags, uint8_t ns)
{
struct dcldata data[NR_DECLARATORS+2];
register struct dcldata *bp;
@@ -147,19 +155,11 @@ declarator(Type *tp, int8_t flags)
memset(data, 0, sizeof(data));
data[NR_DECLARATORS].op = 255;
- for (bp = declarator0(data); bp >= data; --bp) {
- switch (bp->op) {
- case PTR:
- tp = mktype(tp, PTR, NULL);
- break;
- case ARY:
- tp = mktype(tp, ARY, &bp->u.nelem);
- break;
- case FTN:
- tp = mktype(tp, FTN, bp->u.pars);
- break;
- case IDEN:
- sym = bp->u.sym;
+ for (bp = declarator0(data, ns)-1; bp >= data; --bp) {
+ if (bp->op != IDEN) {
+ tp = mktype(tp, bp->op, bp->nelem, bp->data);
+ } else {
+ sym = bp->data;
if (flags == ID_EXPECTED && *sym->name == '\0')
error("missed identifier in declaration");
if (flags == ID_FORBIDDEN && *sym->name != '\0')
@@ -231,7 +231,7 @@ specifier(int8_t *sclass)
if (dcl) {
if (size || sign)
goto invalid_type;
- tp = aggregate(dcl);
+ tp = (*dcl)();
} else {
next();
}
@@ -253,9 +253,7 @@ invalid_type:
static struct node *
initializer(Symbol *sym)
{
- register Type *tp = sym->type;
-
- if (!sym->s.isdefined)
+ if (!sym->isdefined)
error("'%s' initialized and declared extern", sym->name);
if (accept('{')) {
@@ -266,72 +264,14 @@ initializer(Symbol *sym)
expr();
} while (accept(','));
}
+ return NULL;
}
-/* TODO: bitfields */
-
-static void
-newfield(Type *tp, Symbol *sym)
-{
- register Field *p, *q;
- register char *s, *t;
-
- s = sym->name;
- for (q = p = tp->u.fields; p; q = p, p = p->next) {
- t = p->name;
- if (*s == *t && !strcmp(s, t))
- error("duplicated fields '%s' and '%s'", s, t);
- if (sym->u.i == p->id)
- error("duplicated enumeration fields '%s' and '%s'",
- s, t);
- }
-
- p = xmalloc(sizeof(*p));
- p->name = xstrdup(s);
- p->next = NULL;
- p->id = sym->id;
- p->type = sym->type;
- if (!q)
- tp->u.fields = p;
- else
- q->next = p;
-
- return;
-}
-
-static void
-fielddcl(Type *base)
-{
- Type *tp;
- Symbol *sym;
-
- switch (yytoken) {
- case SCLASS:
- error("storage class '%s' in struct/union field", yytext);
- case IDEN: case TYPE: case TYPEIDEN: case TQUALIFIER:
- tp = specifier(NULL);
- case ';':
- break;
- default:
- unexpected();
- }
-
- if (yytoken != ';') {
- do {
- sym = declarator(tp, ID_EXPECTED);
- newfield(base, sym);
- } while (accept(','));
- }
-
- expect(';');
- return;
-}
-
-static Type *
+static Symbol *
newtag(uint8_t tag)
{
register Symbol *sym;
- register Type *tp;
+ static uint8_t ns = NS_STRUCTS;
switch (yytoken) {
case IDEN: case TYPEIDEN:
@@ -343,32 +283,81 @@ newtag(uint8_t tag)
sym = install("", NS_TAG);
break;
}
- if (!sym->type)
- sym->type = mktype(NULL, tag, NULL);
- tp = sym->type;
- if (tp->op != tag)
+ if (!sym->type) {
+ if (ns == NS_STRUCTS + NR_MAXSTRUCTS)
+ error("too much tags declared");
+ sym->type = mktype(NULL, tag, 0, NULL);
+ sym->type->ns = ns++;
+ }
+
+ if (sym->type->op != tag)
error("'%s' defined as wrong kind of tag", yytext);
- return tp;
+ return sym;
}
+/* TODO: bitfields */
+
static Type *
structdcl(void)
{
- Type *tp;
- uint8_t tag;
+ Type *tagtype, *buff[NR_MAXSTRUCTS], **bp = &buff[0];
+ Symbol *tagsym, *sym;
+ uint8_t tag, n;
+ size_t siz;
tag = yylval.token;
next();
- tp = newtag(tag);
- if (accept('{')) {
- if (tp->defined)
- error("redefinition of struct/union '%s'", yytext);
- tp->defined = 1;
- while (!accept('}'))
- fielddcl(tp);
+ tagsym = newtag(tag);
+ tagtype = tagsym->type;
+ if (!accept('{'))
+ return tagtype;
+
+ if (tagtype->defined)
+ error("redefinition of struct/union '%s'", yytext);
+ tagtype->defined = 1;
+ emitstruct(tagsym);
+
+ while (!accept('}')) {
+ Type *base, *tp;
+
+ switch (yytoken) {
+ case SCLASS:
+ error("storage class '%s' in struct/union field",
+ yytext);
+ case IDEN: case TYPE: case TYPEIDEN: case TQUALIFIER:
+ base = specifier(NULL);
+ break;
+ case ';':
+ next();
+ continue;
+ default:
+ unexpected();
+ }
+
+ if (accept(';'))
+ error("identifier expected");
+
+ do {
+ sym = declarator(base, ID_EXPECTED, tagtype->ns);
+ sym->isfield = 1;
+ tp = sym->type;
+ if (tp->op == FTN)
+ error("invalid type in struct/union");
+ if (bp == &buff[NR_MAXSTRUCTS])
+ error("too much fields in struct/union");
+ *bp++ = sym->type;
+ emitdcl(sym);
+ } while (accept(','));
+ expect(';');
}
- return tp;
+ emitestruct();
+ if ((n = bp - buff) != 0) {
+ siz = sizeof(Type *) * n;
+ tagtype->n.elem = n;
+ tagtype->pars = memcpy(xmalloc(siz), buff, siz);
+ }
+ return tagtype;
}
static Type *
@@ -379,7 +368,8 @@ enumdcl(void)
int val = 0;
next();
- tp = newtag(ENUM);
+ tp = newtag(ENUM)->type;
+
if (yytoken == ';')
return tp;
@@ -390,12 +380,11 @@ enumdcl(void)
while (yytoken != '}') {
if (yytoken != IDEN)
unexpected();
- sym = newiden();
+ sym = newiden(NS_IDEN);
sym->type = inttype;
if (accept('='))
initializer(sym);
sym->u.i = val++;
- newfield(tp, sym);
if (!accept(','))
break;
}
@@ -404,7 +393,7 @@ enumdcl(void)
return tp;
}
-static Type *
+static Symbol *
parameter(void)
{
Symbol *sym;
@@ -412,21 +401,25 @@ parameter(void)
Type *tp;
if ((tp = specifier(&sclass)) == voidtype)
- return tp;
- sym = declarator(tp, ID_ACCEPTED);
- sym->s.isdefined = 1;
- /* TODO: check type of the parameter */
+ return NULL;
+ sym = declarator(tp, ID_ACCEPTED, NS_IDEN);
+ sym->isparameter = 1;
+ tp = sym->type;
+ if (tp->op == FTN)
+ error("incorrect function type for a function parameter");
+ if (tp->op == ARY)
+ tp = mktype(tp->type, PTR, 0, NULL);
switch (sclass) {
case REGISTER:
- sym->s.isregister = 1;
+ sym->isregister = 1;
break;
case 0:
- sym->s.isauto = 1;
+ sym->isauto = 1;
break;
default:
error("bad storage class in function parameter");
}
- return sym->type;
+ return sym;
}
void
@@ -441,22 +434,21 @@ decl(void)
return;
do {
- sym = declarator(tp, ID_EXPECTED);
- sym->s.isdefined = 1;
- isfun = sym->type->op != FTN;
+ sym = declarator(tp, ID_EXPECTED, NS_IDEN);
+ isfun = sym->type->op == FTN;
switch (sclass) {
case TYPEDEF:
sym->token = TYPEIDEN;
continue;
case STATIC:
- sym->s.isstatic = 1;
+ sym->isstatic = 1;
break;
case EXTERN:
- sym->s.isdefined = 0;
+ sym->isdefined = 0;
break;
case REGISTER:
- sym->s.isregister = 1;
+ sym->isregister = 1;
if (isfun)
goto bad_function;
break;
@@ -465,7 +457,7 @@ decl(void)
goto bad_function;
/* passtrough */
default:
- sym->s.isauto = 1;
+ sym->isauto = 1;
break;
}
if (accept('='))
@@ -490,7 +482,7 @@ typename(void)
tp = specifier(&sclass);
if (sclass)
error("class storage in type name");
- sym = declarator(tp, ID_FORBIDDEN);
+ sym = declarator(tp, ID_FORBIDDEN, NS_IDEN);
return sym->type;
}
@@ -508,20 +500,19 @@ extdecl(void)
if (accept(';'))
return;
do {
- sym = declarator(base, ID_EXPECTED);
+ sym = declarator(base, ID_EXPECTED, NS_IDEN);
tp = sym->type;
- sym->s.isstatic = 1;
- sym->s.isglobal= 1;
- sym->s.isdefined = 1;
+ sym->isstatic = 1;
+ sym->isglobal= 1;
switch (sclass) {
case REGISTER: case AUTO:
error("incorrect storage class for file-scope declaration");
case STATIC:
- sym->s.isglobal = 0;
+ sym->isglobal = 0;
break;
case EXTERN:
- sym->s.isdefined = 0;
+ sym->isdefined = 0;
break;
case TYPEDEF:
sym->token = TYPEIDEN;
@@ -535,8 +526,9 @@ extdecl(void)
} else if (yytoken == '{') {
curfun = sym;
emitfun(sym);
- context(NULL, NULL, NULL);
+ compound(NULL, NULL, NULL);
emitefun();
+ popctx();
return;
}
} while (accept(','));
diff --git a/cc1/expr.c b/cc1/expr.c
@@ -32,7 +32,7 @@ promote(Node *np)
if (options.npromote)
return np;
tp = np->type;
- r = tp->u.rank;
+ r = tp->n.rank;
if (r > RANK_UINT || tp == inttype || tp == uinttype)
return np;
return castcode(np, (r == RANK_UINT) ? uinttype : inttype);
@@ -51,7 +51,7 @@ typeconv(Node **p1, Node **p2)
tp1 = np1->type;
tp2 = np2->type;
if (tp1 != tp2) {
- if ((n = tp1->u.rank - tp2->u.rank) > 0)
+ if ((n = tp1->n.rank - tp2->n.rank) > 0)
np2 = castcode(np2, tp1);
else if (n < 0)
np1 = castcode(np1, tp2);
@@ -74,7 +74,7 @@ eval(Node *np)
{
if (!np)
return NULL;
- if (!ISNODECMP(np))
+ if (!ISNODELOG(np))
return np;
return ternarycode(np, symcode(one), symcode(zero));
}
@@ -114,7 +114,7 @@ integeruop(char op, Node *np)
static Node *
decay(Node *np)
{
- return unarycode(OADDR, mktype(np->type, PTR, NULL), np);
+ return unarycode(OADDR, mktype(np->type, PTR, 0, NULL), np);
}
/*
@@ -292,19 +292,20 @@ logic(char op, Node *np1, Node *np2)
static Node *
field(Node *np)
{
- Field *fp;
+ extern uint8_t lex_ns;
+ Symbol *sym;
- if (yytoken != IDEN)
- unexpected();
switch (np->typeop) {
case STRUCT: case UNION:
- for (fp = np->type->u.fields; fp; fp = fp->next) {
- if (!strcmp(fp->name, yytext)) {
- next();
- return fieldcode(np, fp);
- }
- }
- error("field '%s' not found", yytext);
+ lex_ns = np->type->ns;
+ next();
+ if (yytoken != IDEN)
+ unexpected();
+ if ((sym = yylval.sym) == NULL)
+ error("incorrect field in struct/union");
+ lex_ns = NS_IDEN;
+ next();
+ return fieldcode(np, sym);
default:
error("struct or union expected");
}
@@ -376,9 +377,9 @@ address(char op, Node *np)
{
if (!np->b.lvalue)
error("lvalue required in unary expression");
- if (np->b.symbol && np->u.sym->s.isregister)
+ if (np->b.symbol && np->u.sym->isregister)
error("address of register variable '%s' requested", yytext);
- return unarycode(op, mktype(np->type, PTR, 0), np);
+ return unarycode(op, mktype(np->type, PTR, 0, NULL), np);
}
static Node *
@@ -435,8 +436,7 @@ primary(void)
expect(')');
break;
default:
- np = NULL;
- break;
+ unexpected();
}
return np;
}
@@ -483,7 +483,6 @@ postfix(void)
case INDIR:
np1 = content(OPTR, np1);
case '.':
- next();
np1 = field(np1);
break;
case '(':
@@ -545,12 +544,12 @@ unary(void)
op = (yytoken == INC) ? OA_ADD : OA_SUB;
next();
return incdec(unary(), op);
- case '!': op = 0; fun = negation; break;
- case '+': op = OADD; fun = numericaluop; break;
- case '-': op = ONEG; fun = numericaluop; break;
- case '~': op = OCPL; fun = integeruop; break;
- case '&': op = OADDR; fun = address; break;
- case '*': op = OPTR; fun = content; break;
+ case '!': op = 0; fun = negation; break;
+ case '+': op = OADD; fun = numericaluop; break;
+ case '-': op = ONEG; fun = numericaluop; break;
+ case '~': op = OCPL; fun = integeruop; break;
+ case '&': op = OADDR; fun = address; break;
+ case '*': op = OPTR; fun = content; break;
default: return postfix();
}
@@ -559,15 +558,17 @@ unary(void)
}
static Node *
-cast2(void)
+cast(void)
{
register Node *np1, *np2;
register Type *tp;
- switch(yytoken) {
+ if (!accept('('))
+ return unary();
+
+ switch (yytoken) {
case TQUALIFIER: case TYPE:
tp = typename();
- expect(')');
switch (tp->op) {
case ARY:
error("cast specify an array type");
@@ -582,17 +583,12 @@ cast2(void)
}
break;
default:
- np2 = unary();
- expect(')');
+ np2 = expr();
break;
}
- return np2;
-}
+ expect(')');
-static Node *
-cast(void)
-{
- return (accept('(')) ? cast2() : unary();
+ return np2;
}
static Node *
diff --git a/cc1/lex.c b/cc1/lex.c
@@ -10,6 +10,7 @@
#include "cc1.h"
static FILE *yyin;
+uint8_t lex_ns = NS_IDEN;
const char *filename;
unsigned linenum;
@@ -181,7 +182,7 @@ end_string:
*bp = '\0';
sym = install("", NS_IDEN);
sym->u.s = xstrdup(buf);
- sym->type = mktype(chartype, PTR, 0);
+ sym->type = mktype(chartype, PTR, 0, NULL);
yylval.sym = sym;
return STRING;
}
@@ -202,7 +203,7 @@ iden(void)
*bp = '\0';
ungetc(c, yyin);
- sym = yylval.sym = lookup(yytext, NS_IDEN);
+ sym = yylval.sym = lookup(yytext, lex_ns);
if (!sym || sym->token == IDEN)
return IDEN;
yylval.token = sym->u.token;
diff --git a/cc1/stmt.c b/cc1/stmt.c
@@ -31,24 +31,30 @@ label(char *s, char define)
if ((sym = lookup(s, NS_LABEL)) != NULL) {
if (define) {
- if (sym->s.isdefined)
+ if (sym->isdefined)
error("label '%s' already defined", s);
- sym->s.isdefined = 1;
+ sym->isdefined = 1;
}
return sym;
}
sym = install(s, NS_LABEL);
- sym->s.isdefined = define;
+ sym->isdefined = define;
return sym;
}
static void
stmtexp(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
{
- if (yytoken != ';')
- emitexp(expr());
+ Node *np = NULL;;
+
+ if (yytoken != ';') {
+ np = expr();
+ emitexp(np);
+ }
+
expect(';');
+ freetree(np);
}
static Node *
@@ -82,6 +88,7 @@ While(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
emitjump(begin, np);
emiteloop();
emitlabel(end);
+ freetree(np);
}
static void
@@ -96,11 +103,11 @@ For(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
expect(FOR);
expect('(');
- einit = expr();
+ einit = (yytoken != ';') ? expr() : NULL;
expect(';');
- econd = expr();
+ econd = (yytoken != ';') ? expr() : NULL;
expect(';');
- einc = expr();
+ einc = (yytoken != ')') ? expr() : NULL;
expect(')');
emitexp(einit);
@@ -113,12 +120,16 @@ For(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
emitjump(begin, econd);
emiteloop();
emitlabel(end);
+ freetree(einit);
+ freetree(econd);
+ freetree(einc);
}
static void
Dowhile(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
{
Symbol *begin, *end;
+ Node *np;
begin = install("", NS_LABEL);
end = install("", NS_LABEL);
@@ -127,9 +138,11 @@ Dowhile(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
emitlabel(begin);
stmt(end, begin, lswitch);
expect(WHILE);
- emitjump(begin, condition());
+ np = condition();
+ emitjump(begin, np);
emiteloop();
emitlabel(end);
+ freetree(np);
}
static void
@@ -139,7 +152,7 @@ Return(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
Type *tp = curfun->type->type;
expect(RETURN);
- np = eval(expr());
+ np = (yytoken != ';') ? eval(expr()) : NULL;
expect(';');
if (!np) {
if (tp != voidtype)
@@ -153,6 +166,7 @@ Return(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
}
emitret(tp);
emitexp(np);
+ freetree(np);
}
static void
@@ -215,8 +229,7 @@ Switch(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
expect(SWITCH);
expect ('(');
- if ((cond = expr()) == NULL)
- unexpected();
+ cond = expr();
if ((cond = convert(cond, inttype, 0)) == NULL)
error("incorrect type in switch statement");
expect (')');
@@ -230,11 +243,13 @@ Switch(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
for (p = lcase.head; p; p = next) {
emitcase(p->label, p->expr);
next = p->next;
+ freetree(p->expr);
free(p);
}
if (lcase.deflabel)
emitdefault(lcase.deflabel);
emitlabel(lbreak);
+ freetree(cond);
}
static void
@@ -246,8 +261,7 @@ Case(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
expect(CASE);
if (!lswitch)
error("case label not within a switch statement");
- if ((np = expr()) == NULL)
- unexpected();
+ np = expr();
if ((np = convert(np, inttype, 0)) == NULL)
error("incorrect type in case statement");
expect(':');
@@ -291,17 +305,19 @@ If(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
} else {
emitlabel(lelse);
}
+ freetree(np);
}
void
compound(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
{
+ pushctx();
expect('{');
+
for (;;) {
switch (yytoken) {
case '}':
- next();
- return;
+ goto end_compound;
case TYPEIDEN:
if (ahead() == ':')
goto statement;
@@ -314,15 +330,21 @@ compound(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
stmt(lbreak, lcont, lswitch);
}
}
+
+end_compound:
+ popctx();
+ expect('}');
+ return;
}
static void
stmt(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
{
void (*fun)(Symbol *lbreak, Symbol *lcont, Caselist *lswitch);
+ Node *np;
switch (yytoken) {
- case '{': fun = context; break;
+ case '{': fun = compound; break;
case RETURN: fun = Return; break;
case WHILE: fun = While; break;
case FOR: fun = For; break;
@@ -340,9 +362,10 @@ stmt(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
break;
case '@':
next();
- emitprint(expr());
- break;
- next();
+ np = expr();
+ emitprint(np);
+ freetree(np);
+ return;
}
(*fun)(lbreak, lcont, lswitch);
}
diff --git a/cc1/symbol.c b/cc1/symbol.c
@@ -10,8 +10,8 @@
#define NR_SYM_HASH 32
uint8_t curctx;
-short localcnt;
-short globalcnt;
+static short localcnt;
+static short globalcnt;
static struct symtab {
Symbol *head;
@@ -38,8 +38,10 @@ freesyms(uint8_t ns)
for (sym = tbl->head; sym; sym = next) {
if (sym->ctx <= curctx)
break;
- if (ns == NS_LABEL && !sym->s.isdefined)
+ if (ns == NS_LABEL && !sym->isdefined)
error("label '%s' is not defined", sym->name);
+ if (ns == NS_TAG)
+ sym->type->defined = 0;
tbl->htab[hash(sym->name)] = sym->hash;
next = tbl->head = sym->next;
free(sym->name);
@@ -47,26 +49,19 @@ freesyms(uint8_t ns)
}
}
-Type *
-aggregate(Type * (*fun)(void))
+void
+pushctx(void)
{
- Type *tp;
-
++curctx;
- tp = (*fun)();
- --curctx;
- freesyms(NS_IDEN);
- return tp;
}
void
-context(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
+popctx(void)
{
- ++curctx;
- compound(lbreak, lcont, lswitch);
--curctx;
freesyms(NS_IDEN);
freesyms(NS_TAG);
+ freesyms(NS_STRUCTS);
if (curctx == 0) {
localcnt = 0;
freesyms(NS_LABEL);
@@ -79,9 +74,9 @@ lookup(register char *s, uint8_t ns)
struct symtab *tbl;
register Symbol *sym;
- tbl = &symtab[ns];
+ tbl = &symtab[(ns > NS_STRUCTS) ? NS_STRUCTS : ns];
for (sym = tbl->htab[hash(s)]; sym; sym = sym->hash) {
- if (!strcmp(sym->name, s))
+ if (!strcmp(sym->name, s) && sym->ns == ns)
return sym;
}
@@ -99,8 +94,9 @@ install(char *s, uint8_t ns)
sym->ctx = curctx;
sym->token = IDEN;
sym->id = (curctx) ? ++localcnt : ++globalcnt;
- sym->s.isdefined = 1;
- tbl = &symtab[ns];
+ sym->isdefined = 1;
+ sym->ns = ns;
+ tbl = &symtab[(ns > NS_STRUCTS) ? NS_STRUCTS : ns];
sym->next = tbl->head;
tbl->head = sym;
diff --git a/cc1/types.c b/cc1/types.c
@@ -23,96 +23,96 @@ Type
.op = INT,
.letter = L_BOOL,
.defined = 1,
- .u.rank = RANK_BOOL
+ .n.rank = RANK_BOOL
},
*schartype = &(Type) {
.op = INT,
.letter = L_SCHAR,
.defined = 1,
- .u.rank = RANK_SCHAR
+ .n.rank = RANK_SCHAR
},
*uchartype = &(Type) {
.op = INT,
.letter = L_UCHAR,
.sign = 1,
.defined = 1,
- .u.rank = RANK_UCHAR
+ .n.rank = RANK_UCHAR
},
*chartype = &(Type) {
.op = INT,
.letter = L_CHAR,
.sign = 1,
.defined = 1,
- .u.rank = RANK_CHAR
+ .n.rank = RANK_CHAR
},
*ushortype = &(Type) {
.op = INT,
.letter = L_USHORT,
.defined = 1,
- .u.rank = RANK_USHORT
+ .n.rank = RANK_USHORT
},
*shortype = &(Type) {
.op = INT,
.letter = L_SHORT,
.defined = 1,
- .u.rank = RANK_SHORT
+ .n.rank = RANK_SHORT
},
*uinttype = &(Type) {
.op = INT,
.letter = L_UINT,
.sign = 1,
.defined = 1,
- .u.rank = RANK_UINT
+ .n.rank = RANK_UINT
},
*inttype = &(Type) {
.op = INT,
.letter = L_INT,
.defined = 1,
- .u.rank = RANK_INT
+ .n.rank = RANK_INT
},
*longtype = &(Type) {
.op = INT,
.letter = L_LONG,
.defined = 1,
- .u.rank = RANK_LONG
+ .n.rank = RANK_LONG
},
*ulongtype = &(Type) {
.op = INT,
.letter = L_ULONG,
.sign = 1,
.defined = 1,
- .u.rank = RANK_ULONG
+ .n.rank = RANK_ULONG
},
*ullongtype = &(Type) {
.op = INT,
.letter = L_ULLONG,
.sign = 1,
.defined = 1,
- .u.rank = RANK_ULLONG
+ .n.rank = RANK_ULLONG
},
*llongtype = &(Type) {
.op = INT,
.letter = L_LLONG,
.defined = 1,
- .u.rank = RANK_LLONG
+ .n.rank = RANK_LLONG
},
*floattype = &(Type) {
.op = FLOAT,
.letter = L_FLOAT,
.defined = 1,
- .u.rank = RANK_FLOAT
+ .n.rank = RANK_FLOAT
},
*doubletype = &(Type) {
.op = FLOAT,
.letter = L_DOUBLE,
.defined = 1,
- .u.rank = RANK_DOUBLE
+ .n.rank = RANK_DOUBLE
},
*ldoubletype = &(Type) {
.op = FLOAT,
.letter = L_LDOUBLE,
.defined = 1,
- .u.rank = RANK_LDOUBLE
+ .n.rank = RANK_LDOUBLE
};
Type *
@@ -186,111 +186,74 @@ invalid_type:
}
Type *
-mktype(Type *tp, uint8_t op, void *data)
+mktype(Type *tp, uint8_t op, short nelem, void *data)
{
- static Type *typetab[NR_TYPE_HASH], **tbl;
- static uint8_t t, def;
+ static Type *typetab[NR_TYPE_HASH], **tbl, type;
+ static uint8_t t;
register Type *bp;
- char letter, look;
- union typeval u;
+ static char letters[] = {
+ [PTR] = L_POINTER, [ARY] = L_ARRAY,
+ [FTN] = L_FUNCTION, [ENUM] = L_INT,
+ [STRUCT] = L_STRUCT, [UNION] = L_UNION
+ };
- switch (op) {
- case PTR:
- if (tp == voidtype)
- return pvoidtype;
- letter = L_POINTER;
- def = 1;
- look = 1;
- break;
- case ARY:
- u.nelem = *(unsigned short *) data;
- letter = L_ARRAY;
- def = u.nelem != 0;
- look = 1;
- break;
- case FTN:
- u.pars = data;
- letter = L_FUNCTION;
- def = 1;
- look = 0;
- break;
- case ENUM:
- letter = L_INT;
- def = 1;
- look = 0;
- break;
- case STRUCT: case UNION:
- letter = (op == STRUCT) ? L_STRUCT : L_UNION;
- def = 0;
- look = 0;
- u.fields = NULL;
- break;
- default:
- fputs("internal type error, aborting\n", stderr);
- abort();
- }
+ if (op == PTR && tp == voidtype)
+ return pvoidtype;
- t = (op ^ (uint8_t) ((unsigned short) tp >> 3))
- & NR_TYPE_HASH-1;
+ type.type = tp;
+ type.op = op;
+ type.sign = 0;
+ type.letter = letters[op];
+ type.pars = data;
+ type.n.elem = nelem;
+ type.ns = 0;
+
+ if (op == ARY && nelem == 0 || op == STRUCT || op == UNION)
+ type.defined = 0;
+ else
+ type.defined = 1;
+
+ t = (op ^ (uint8_t) ((unsigned short) tp >> 3)) & NR_TYPE_HASH-1;
tbl = &typetab[t];
- if (look) {
- for (bp = *tbl; bp; bp = bp->next) {
- if (bp->type == tp && bp->op == op &&
- (op != ARY || bp->u.nelem == u.nelem)) {
- return bp;
- }
+ for (bp = *tbl; bp; bp = bp->next) {
+ if (eqtype(bp, &type)) {
+ free(data);
+ return bp;
}
}
- bp = xcalloc(1, sizeof(*bp));
+ bp = xmalloc(sizeof(*bp));
+ *bp = type;
bp->next = *tbl;
- bp->type = tp;
- bp->op = op;
- bp->letter = letter;
- bp->defined = def;
- bp->u = u;
return *tbl = bp;
}
bool
eqtype(Type *tp1, Type *tp2)
{
+ uint8_t n;
+ Type **p1, **p2;
+
if (tp1 == tp2)
return 1;
- if (tp1->op != tp2->op)
+ if (tp1->op != tp2->op || tp1->n.elem != tp2->n.elem)
return 0;
switch (tp1->op) {
+ case ARY:
case PTR:
return eqtype(tp1->type, tp2->type);
- /* TODO: use the same struct for function parameters and fields */
- case FTN: {
- Funpar *fp1 = tp1->u.pars, *fp2 = tp2->u.pars;
-
- while (fp1 && fp2) {
- if (!eqtype(fp1->type, fp2->type))
- break;
- fp1 = fp1->next;
- fp2 = fp2->next;
- }
- return fp1 == fp2;
- }
case UNION:
- case STRUCT: {
- Field *fp1 = tp1->u.fields, *fp2 = tp2->u.fields;
-
- while (fp1 && fp2) {
- if (!eqtype(fp1->type, fp2->type))
- break;
- fp1 = fp1->next;
- fp2 = fp2->next;
+ case STRUCT:
+ case FTN:
+ p1 = tp1->pars, p2 = tp2->pars;
+ for (n = tp1->n.elem; n != 0; --n) {
+ if (!eqtype(*p1++, *p2++))
+ return 0;
}
- return fp1 == fp2;
- }
- case ARY:
- if (!eqtype(tp1->type, tp2->type))
- return 0;
- return tp1->u.nelem == tp2->u.nelem;
- case ENUM: case INT: case FLOAT:
+ return 1;
+ case ENUM:
+ /* TODO: Check when two enum are the same type */
+ case INT: case FLOAT:
return tp1->letter == tp2->letter;
default:
fputs("internal type error, aborting\n", stderr);
diff --git a/cc2/Makefile b/cc2/Makefile
@@ -1,5 +1,5 @@
-OBJS = main.o parser.o cgen.o
+OBJS = main.o parser.o cgen.o code.o optm.o
CPPFLAGS = -I../inc
LDFLAGS = -L../lib
diff --git a/cc2/cc2.h b/cc2/cc2.h
@@ -1,12 +1,16 @@
+typedef struct symbol Symbol;
+typedef struct node Node;
+
typedef struct {
short size;
uint8_t align;
+ char letter;
bool sign : 1;
bool c_int : 1;
} Type;
-typedef struct symbol {
+struct symbol {
char *name;
bool public : 1;
bool extrn : 1;
@@ -23,11 +27,12 @@ typedef struct symbol {
struct {
short locals;
short params;
+ Node **body;
} f;
} u;
-} Symbol;
+};
-typedef struct node {
+struct node {
char op;
char subop;
Type *type;
@@ -39,7 +44,7 @@ typedef struct node {
char reg;
} u;
struct node *left, *right;
-} Node;
+};
enum nerrors {
EINTNUM, /* too much internal identifiers */
@@ -94,7 +99,23 @@ enum nerrors {
#define ADDABLE 10
+
+enum {
+ PUSH, POP, LD, ADD, RET, ADDI, LDI, ADDR, ADDX, ADCX, LDX,
+ LDFX
+};
+
+enum {
+ A = 1, B, C, D, E, H, L, IYL, IYH, NREGS,
+ IXL, IXH, F, I, SP, AF, HL, DE, BC, IX, IY
+};
+
extern void error(unsigned nerror, ...);
-extern void genaddable(Node *list[]);
-extern void generate(Symbol *sym, Node *list[]);
+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 Node *optimize(Node *np);
+extern void prtree(Node *np);
diff --git a/cc2/cgen.c b/cc2/cgen.c
@@ -9,85 +9,10 @@
#include <stdio.h>
-/* TODO: Change emit to code */
-enum {
- PUSH, POP, LD, ADD, RET, ADDI, LDI, ADDR, ADDX, ADCX, LDX,
- LDFX
-};
-
-enum {
- A = 1, B, C, D, E, H, L, IYL, IYH, NREGS,
- IXL, IXH, F, I, SP, AF, HL, DE, BC, IX, IY
-};
-
-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 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};
-void
-emit(char op, ...)
-{
- va_list va;
- uint8_t reg1, reg2;
- TINT imm;
- short off;
- char *label;
-
- va_start(va, op);
- switch (op) {
- case RET:
- printf("\t%s\n", opnames[op]);
- break;
- case PUSH: case POP:
- reg1 = va_arg(va, int);
- printf("\t%s\t%s\n", opnames[op], regnames[reg1]);
- break;
- case ADD: case LD:
- reg1 = va_arg(va, int);
- reg2 = va_arg(va, int);
- printf("\t%s\t%s,%s\n",
- opnames[op], regnames[reg1], regnames[reg2]);
- break;
- case ADDI: case LDI:
- reg1 = va_arg(va, int);
- imm = va_arg(va, int);
- printf("\t%s\t%s,%d\n", opnames[op], regnames[reg1], imm);
- break;
- case ADDX: case ADCX: case LDFX:
- reg1 = va_arg(va, int);
- reg2 = va_arg(va, int);
- off = va_arg(va, int);
- printf("\t%s\t%s,(%s%+d)\n",
- opnames[op], regnames[reg1], regnames[reg2], off);
- break;
- case LDX:
- reg1 = va_arg(va, int);
- off = va_arg(va, int);
- reg2 = va_arg(va, int);
- printf("\t%s\t(%s%+d),%s\n",
- opnames[op], regnames[reg1], off, regnames[reg2]);
- break;
- case ADDR:
- label = va_arg(va, char *);
- printf("%s:\n", label);
- break;
- }
-
- va_end(va);
-}
static char
allocreg(Node *np)
@@ -136,11 +61,11 @@ move(Node *np)
sym = np->u.sym;
switch (tp->size) {
case 1:
- emit(LDFX, reg, IX, sym->u.v.off);
+ code(LDFX, reg, IX, sym->u.v.off);
break;
case 2:
- emit(LDFX, lower[reg], IX, sym->u.v.off);
- emit(LDFX, upper[reg], IX, sym->u.v.off+1);
+ code(LDFX, lower[reg], IX, sym->u.v.off);
+ code(LDFX, upper[reg], IX, sym->u.v.off+1);
break;
case 4:
case 8:
@@ -168,7 +93,7 @@ conmute(Node *np)
}
static void
-cgen(Node *np)
+cgen(Node *np, Node *parent)
{
Node *lp, *rp;
TINT imm;
@@ -179,25 +104,26 @@ cgen(Node *np)
lp = np->left;
rp = np->right;
if (np->addable >= ADDABLE) {
+ if (parent && parent->op == OASSIG)
+ return;
move(np);
return;
}
if (!lp) {
- cgen(rp);
+ cgen(rp, np);
} else if (!rp) {
- cgen(lp);
+ cgen(lp, np);
} else {
Node *p, *q;
if (lp->complex > rp->complex)
p = lp, q = rp;
else
p = rp, q = lp;
- cgen(p);
- cgen(q);
+ cgen(p, np);
+ cgen(q, np);
}
- assert(lp && lp->op == REG || rp && rp->op == REG);
switch (np->op) {
case OADD:
switch (np->type->size) {
@@ -208,10 +134,12 @@ cgen(Node *np)
rp = np->right;
} else if (lp->u.reg != A) {
/* TODO: Move A to variable */
- emit(PUSH, AF);
- emit(LD, A, lp->u.reg);
+ code(PUSH, AF);
+ code(LD, A, lp->u.reg);
}
- emit(ADD, A, rp->u.reg);
+ code(ADD, A, rp->u.reg);
+ np->op = REG;
+ np->u.reg = A;
break;
case 2:
if (rp->u.reg == HL || rp->u.reg == IY) {
@@ -220,62 +148,88 @@ cgen(Node *np)
rp = np->right;
} else if (lp->u.reg != HL && lp->u.reg != IY) {
/* TODO: Move HL to variable */
- emit(PUSH, HL);
- emit(LD, H, upper[lp->u.reg]);
- emit(LD, L, lower[lp->u.reg]);
+ code(PUSH, HL);
+ code(LD, H, upper[lp->u.reg]);
+ code(LD, L, lower[lp->u.reg]);
}
- emit(ADD, lp->u.reg, rp->u.reg);
+ code(ADD, lp->u.reg, rp->u.reg);
+ np->op = REG;
+ np->u.reg = lp->u.reg;
break;
case 4:
case 8:
abort();
}
break;
+ case OASSIG:
+ switch (np->type->size) {
+ case 1:
+ switch (lp->op) {
+ case AUTO:
+ code(LDX, IX, lp->u.sym->u.v.off, rp->u.reg);
+ break;
+ case REG:
+ case MEM:
+ default:
+ abort();
+ }
+ break;
+ default:
+ abort();
+ }
+ break;
default:
abort();
}
}
+static Node *
+applycgen(Node *np)
+{
+ cgen(np, NULL);
+ return NULL;
+}
+
void
-generate(Symbol *sym, Node *list[])
+generate(Symbol *fun)
{
extern char odebug;
- Node *np;
- char frame = sym->u.f.locals != 0 || odebug;
+ char frame = fun->u.f.locals != 0 || odebug;
- emit(ADDR, sym->name);
+ code(ADDR, fun->name);
if (frame) {
- emit(PUSH, IX);
- emit(LD, IX, SP);
- emit(LDI, HL, -sym->u.f.locals);
- emit(ADD, HL, SP);
- emit(LD, SP, HL);
+ code(PUSH, IX);
+ code(LD, IX, SP);
+ code(LDI, HL, -fun->u.f.locals);
+ code(ADD, HL, SP);
+ code(LD, SP, HL);
}
- while (np = *list++)
- cgen(np);
+ apply(fun->u.f.body, applycgen);
if (frame) {
- emit(LD, SP, IX);
- emit(POP, IX);
- emit(RET);
+ code(LD, SP, IX);
+ code(POP, IX);
+ code(RET);
}
}
/*
+ * This is strongly influenced by
+ * http://plan9.bell-labs.com/sys/doc/compiler.ps
* calculate addresability as follows
* AUTO => 11 value+fp
* REGISTER => 13 register
* STATIC => 12 (value)
* CONST => 20 $value
*/
-static void
-xaddable(Node *np)
+Node *
+genaddable(Node *np)
{
Node *lp, *rp;
if (!np)
- return;
+ return np;
np->complex = 0;
np->addable = 0;
@@ -296,14 +250,14 @@ xaddable(Node *np)
break;
default:
if (lp)
- xaddable(lp);
+ genaddable(lp);
if (rp)
- xaddable(rp);
+ genaddable(rp);
break;
}
if (np->addable > 10)
- return;
+ return np;
if (lp)
np->complex = lp->complex;
if (rp) {
@@ -316,15 +270,5 @@ xaddable(Node *np)
}
if (np->complex == 0)
++np->complex;
- return;
+ return np;
}
-
-void
-genaddable(Node *list[])
-{
- Node *np;
-
- while (np = *list++)
- xaddable(np);
-}
-
diff --git a/cc2/code.c b/cc2/code.c
@@ -0,0 +1,69 @@
+
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include <cc.h>
+#include "cc2.h"
+
+
+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",
+ [ADDR] = "a:"
+};
+
+void
+code(char op, ...)
+{
+ va_list va;
+ char *cp, c;
+
+ va_start(va, op);
+ for (cp = opfmt[op]; c = *cp; ++cp) {
+ switch (c) {
+ case 'o':
+ fputs(opnames[op], stdout);
+ break;
+ case 'r':
+ fputs(regnames[va_arg(va, int)], stdout);
+ break;
+ case 'i':
+ printf("%d", va_arg(va, int));
+ break;
+ case 'a':
+ fputs(va_arg(va, char *), stdout);
+ break;
+ default:
+ putchar(c);
+ break;
+ }
+ }
+ putchar('\n');
+
+ va_end(va);
+}
diff --git a/cc2/main.c b/cc2/main.c
@@ -9,8 +9,6 @@
#include "cc2.h"
#include "error.h"
-extern void parse(void);
-
char odebug;
void
@@ -30,5 +28,11 @@ error(unsigned nerror, ...)
int
main(void)
{
- parse();
+ Symbol *fun;
+
+ while (!feof(stdin) && (fun = parse())) {
+ apply(fun->u.f.body, optimize);
+ apply(fun->u.f.body, genaddable);
+ generate(fun);
+ }
}
diff --git a/cc2/optm.c b/cc2/optm.c
@@ -0,0 +1,43 @@
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <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->c_int && np->type->size >= tp->size) {
+ np = np->left;
+ goto repeat;
+ }
+ break;
+ case OASSIG:
+ tp = np->type;
+ break;
+ default:
+ np->type = tp;
+ }
+
+ np->left = optcasts(np->left, tp);
+ np->right = optcasts(np->right, tp);
+ return np;
+}
+
+Node *
+optimize(Node *np)
+{
+ np = optcasts(np, np->type);
+ return np;
+}
diff --git a/cc2/parser.c b/cc2/parser.c
@@ -20,12 +20,13 @@ enum {
};
static Symbol *curfun;
-static Node *stack[NR_STACKSIZ], **stackp = stack;
-static Node *listexp[NR_EXPRESSIONS], **listp = listexp;
-static Node nodepool[NR_NODEPOOL], *newp = nodepool;
+static Node *stack[NR_STACKSIZ], **stackp;
+static Node *listexp[NR_EXPRESSIONS], **listp;
+static Node nodepool[NR_NODEPOOL], *newp;
Type l_int8 = {
+ .letter = L_INT8,
.size = 1,
.align = 2,
.sign = 1,
@@ -33,6 +34,7 @@ Type l_int8 = {
};
Type l_int16 = {
+ .letter = L_INT16,
.size = 2,
.align = 2,
.sign = 1,
@@ -40,6 +42,7 @@ Type l_int16 = {
};
Type l_int32 = {
+ .letter = L_INT32,
.size = 4,
.align = 4,
.sign = 1,
@@ -47,6 +50,7 @@ Type l_int32 = {
};
Type l_int64 = {
+ .letter = L_INT64,
.size = 8,
.align = 8,
.sign = 1,
@@ -54,29 +58,60 @@ Type l_int64 = {
};
Type l_uint8 = {
+ .letter = L_UINT8,
.size = 1,
.align = 2,
.c_int = 1,
};
Type l_uint16 = {
+ .letter = L_UINT16,
.size = 2,
.align = 2,
.c_int = 1,
};
Type l_uint32 = {
+ .letter = L_UINT32,
.size = 4,
.align = 4,
.c_int = 1,
};
Type l_uint64 = {
+ .letter = L_UINT64,
.size = 8,
.align = 8,
.c_int = 1,
};
+
+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 *list[], Node *(*fun)(Node *))
+{
+ Node *np;
+
+ while (np = *list)
+ *list++ = (*fun)(np);
+}
+
static Symbol *
parameter(char *num)
{
@@ -390,17 +425,6 @@ deflabel(char *token)
sym->u.l.addr = listp - listexp;
}
-static void
-endfunction(char *token)
-{
- if (!curfun)
- error(ESYNTAX);
- listp = NULL;
- genaddable(listexp);
- generate(curfun, listexp);
- curfun = NULL;
-}
-
static Symbol *
declaration(uint8_t t, char class, char *token)
{
@@ -444,7 +468,7 @@ globdcl(char *token)
sym->type = FUN;
curfun = sym;
- listp = listexp;
+ sym->u.f.body = listp = listexp;
newp = nodepool;
}
@@ -464,7 +488,7 @@ localdcl(char *token)
sym->u.v.off = 1-curfun->u.f.locals;
}
-void
+Symbol *
parse(void)
{
void (*fun)(char *tok);
@@ -472,6 +496,11 @@ parse(void)
int c;
char line[MAXLINE];
+ curfun = NULL;
+ stackp = stack;
+ listp = listexp;
+ newp = nodepool;
+
for (;;) {
switch (c = getchar()) {
case 'L':
@@ -493,10 +522,15 @@ parse(void)
fun = globdcl;
break;
case '}':
- fun = endfunction;
- break;
+ if (!curfun)
+ error(ESYNTAX);
+ return curfun;
case EOF:
- goto found_eof;
+ if (ferror(stdin))
+ error(EFERROR, strerror(errno));
+ if (curfun)
+ goto syntax_error;
+ return NULL;
case '\n':
continue;
default:
@@ -514,11 +548,10 @@ parse(void)
}
found_eof:
- if (ferror(stdin))
- error(EFERROR, strerror(errno));
- if (!curfun)
- return;
+
+ if (!curfun)
+ return curfun;
syntax_error:
error(ESYNTAX);
}