ref: d90d76bddf5a29e8d393f1803cf3db3330e532bb
parent: c5c6bf38f751f19db8d848e04d989f1da59c0792
author: Roberto E. Vargas Caballero <[email protected]>
date: Thu Mar 12 06:07:04 EDT 2015
Simplify node() function Node() creates a new node, and it was accepting a value that was the kind of node, and a vararg list of descendant. This created a lot of problems, and some ugly unions were needed. This patch simplifies the Node struct and make that node only receives a node operator.
--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -140,23 +140,14 @@
extern uint8_t next(void);
extern void expect(uint8_t tok);
-
typedef struct node {
- void (*code)(struct node *);
+ uint8_t op;
Type *type;
- uint8_t typeop;
- uint8_t nchilds;
- struct {
- bool lvalue : 1;
- bool symbol: 1;
- bool constant : 1;
- } b;
- union unode {
- Symbol *sym;
- Type *type;
- char op;
- } u;
- struct node *childs[];
+ Symbol *sym;
+ bool lvalue : 1;
+ bool symbol: 1;
+ bool constant : 1;
+ struct node *left, *rigth;
} Node;
enum {
@@ -165,7 +156,7 @@
OBAND, OBXOR, OBOR, OASSIGN, OA_MUL, OA_DIV,
OA_MOD, OA_ADD, OA_SUB, OA_SHL, OA_SHR,
OA_AND, OA_XOR, OA_OR, OADDR,ONEG, OCPL, OEXC,
- OCOMMA,
+ OCOMMA, OCAST, OSYM, OASK, OFIELD, OTYP,
/* TODO: This order is important, but must be changed */
OAND, OOR,
/*
@@ -175,10 +166,10 @@
OEQ = 0x40, ONE, OLT, OGE, OLE, OGT
};
+/*TODO: clean these declarations */
extern void
emitdcl(Symbol *), emitefun(void),
- emitsym(Node *), emitunary(Node *),
- emitbin(Node *), emitexp(Node *),
+ emitexp(Node *),
emitprint(Node *), emitlabel(Symbol *), emitjump(Symbol *, Node *),
emitbloop(void), emiteloop(void),
emitswitch(short, Node *), emitcase(Symbol *, Node *),
@@ -187,20 +178,13 @@
emitdefault(Symbol *),
emitstruct(Symbol *sym), emitestruct(void);
-enum {
- CAST, FIELD, UNARY, BINARY,
- SIZEOFCODE, SYMBOL, TERNARY
-};
-
-extern Node *node(char kind, Type *tp, ...);
-
+extern Node *node(uint8_t op, Type *tp, Node *left, Node *rigth);
+extern Node *symbol(Symbol *sym);
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 >= OEQ)
-#define ISNODELOG(n) (ISNODEBIN(n) && (n)->u.op >= OAND)
+#define NEGATE(n, v) ((n)->op ^= (v))
+#define ISNODECMP(n) ((n)->op >= OEQ)
+#define ISNODELOG(n) ((n)->op >= OAND)
extern Node *expr(void);
extern void extdecl(void), decl(void);
--- a/cc1/code.c
+++ b/cc1/code.c
@@ -7,7 +7,11 @@
#include "../inc/cc.h"
#include "cc1.h"
-char *opcodes[] = {
+static void emitbin(Node *), emitunary(Node *), emitternary(Node *),
+ emitcast(Node *), emitsym(Node *), emitfield(Node *),
+ emitsizeof(Node *);
+
+char *optxt[] = {
[OADD] = "+",
[OSUB] = "-",
[OMUL] = "*",
@@ -47,6 +51,50 @@
[OCOMMA] = ","
};
+void (*opcode[])(Node *) = {
+ [OADD] = emitbin,
+ [OSUB] = emitbin,
+ [OMUL] = emitbin,
+ [OINC] = emitunary,
+ [ODEC] = emitunary,
+ [OSIZE] = emitsizeof,
+ [OPTR] = emitunary,
+ [OMOD] = emitbin,
+ [ODIV] = emitbin,
+ [OSHL] = emitbin,
+ [OSHR] = emitbin,
+ [OLT] = emitbin,
+ [OGT] = emitbin,
+ [OGE] = emitbin,
+ [OLE] = emitbin,
+ [OEQ] = emitbin,
+ [ONE] = emitunary,
+ [OBAND] = emitbin,
+ [OBXOR] = emitbin,
+ [OBOR] = emitbin,
+ [OASSIGN] = emitbin,
+ [OA_MUL] = emitbin,
+ [OA_DIV] = emitbin,
+ [OA_MOD] = emitbin,
+ [OA_ADD] = emitbin,
+ [OA_SUB] = emitbin,
+ [OA_SHL] = emitbin,
+ [OA_SHR] = emitbin,
+ [OA_AND] = emitbin,
+ [OA_XOR] = emitbin,
+ [OA_OR] = emitbin,
+ [OADDR] = emitunary,
+ [ONEG] = emitunary,
+ [OCPL] = emitunary,
+ [OAND] = emitbin,
+ [OOR] = emitbin,
+ [OCOMMA] = emitbin,
+ [OCAST] = emitcast,
+ [OSYM] = emitsym,
+ [OASK] = emitternary,
+ [OFIELD]= emitfield
+};
+
void
freetree(Node *np)
{
@@ -54,9 +102,8 @@
if (!np)
return;
-
- for (p = np->childs; np->nchilds--; ++p)
- freetree(*p);
+ freetree(np->left);
+ freetree(np->rigth);
free(np);
}
@@ -86,7 +133,7 @@
emitconst(Node *np)
{
char *bp, c;
- Symbol *sym = np->u.sym;
+ Symbol *sym = np->sym;
if (np->type == inttype) {
printf("#%c%x", np->type->letter, sym->u.i);
@@ -113,7 +160,7 @@
emitsym(Node *np)
{
putchar('\t');
- (np->b.constant) ? emitconst(np) : emitvar(np->u.sym);
+ (np->constant) ? emitconst(np) : emitvar(np->sym);
}
static void
@@ -134,34 +181,34 @@
void
emitcast(Node *np)
{
- Node *child = np->childs[0];
+ Node *lp = np->left;
- (*child->code)(child);
- printf("\t%c%c", child->type->letter, np->type->letter);
+ (*opcode[lp->op])(lp);
+ printf("\t%c%c", lp->type->letter, np->type->letter);
}
void
emitunary(Node *np)
{
- Node *child;
+ Node *lp;
char letter;
letter = np->type->letter;
- child = np->childs[0];
- (*child->code)(child);
- printf("\t%s%c", opcodes[np->u.op], letter);
+ lp = np->left;
+ (*opcode[lp->op])(lp);
+ printf("\t%s%c", optxt[np->op], letter);
}
void
emitbin(Node *np)
{
- Node *child1, *child2;
+ Node *lp, *rp;
- child1 = np->childs[0];
- child2 = np->childs[1];
- (*child1->code)(child1);
- (*child2->code)(child2);
- printf("\t%s%c", opcodes[np->u.op], np->type->letter);
+ lp = np->left;
+ rp = np->rigth;
+ (*opcode[lp->op])(lp);
+ (*opcode[rp->op])(rp);
+ printf("\t%s%c", optxt[np->op], np->type->letter);
}
void
@@ -169,12 +216,12 @@
{
Node *cond, *ifyes, *ifno;
- cond = np->childs[0];
- ifyes = np->childs[1];
- ifno = np->childs[2];
- (*cond->code)(cond);
- (*ifyes->code)(ifyes);
- (*ifno->code)(ifno);
+ cond = np->left;
+ ifyes = np->rigth->left;
+ ifno = np->rigth->rigth;
+ (*opcode[cond->op])(cond);
+ (*opcode[ifyes->op])(ifyes);
+ (*opcode[ifno->op])(ifno);
printf("\t?%c", np->type->letter);
}
@@ -181,7 +228,7 @@
void
emitsizeof(Node *np)
{
- printf("\t#%c", np->u.type->letter);
+ printf("\t#%c", np->left->type->letter);
}
void
@@ -188,7 +235,7 @@
emitexp(Node *np)
{
if (np)
- (*np->code)(np);
+ (*opcode[np->op])(np);
putchar('\n');
}
@@ -195,7 +242,7 @@
void
emitprint(Node *np)
{
- (*np->code)(np);
+ (*opcode[np->op])(np);
printf("\tk%c\n", np->type->letter);
fflush(stdout);
}
@@ -273,97 +320,36 @@
void
emitfield(Node *np)
{
- Node *child;
+ Node *lp = np->left;
- child = np->childs[0];
- (*child->code)(child);
+ (*opcode[lp->op])(lp);
putchar('\t');
- emitvar(np->u.sym);
+ emitvar(np->sym);
}
-enum {
- SYM, TYP, OP
-};
-
-
-/*TODO: Remove type of union unode */
-
-struct kindnode {
- uint8_t nchilds;
- char unode;
- void (*code)(Node *);
-} kindnodes [] = {
- [CAST]= {
- .nchilds = 1,
- .code = emitcast
- },
- [FIELD] = { /*TODO: Create a node for the symbol */
- .nchilds = 1,
- .unode = SYM,
- .code = emitfield
- },
- [UNARY] = {
- .nchilds = 1,
- .unode = OP,
- .code = emitunary
- },
- [BINARY] = {
- .nchilds = 2,
- .unode = OP,
- .code = emitbin
- },
- [SIZEOFCODE] = {
- .nchilds = 0,
- .unode = TYP,
- .code = emitsizeof
- },
- [SYMBOL] = {
- .nchilds = 0,
- .unode = SYM,
- .code = emitsym
- },
- [TERNARY] = {
- .nchilds = 3,
- .code = emitternary
- }
-};
-
Node *
-node(char kind, Type *tp, ...)
+node(uint8_t op, Type *tp, Node *left, Node *rigth)
{
- uint8_t nchilds, i;
- va_list va;
- struct kindnode *kp;
Node *np;
- va_start(va, tp);
- kp = &kindnodes[kind];
- nchilds = kp->nchilds;
- np = xmalloc(sizeof(*np) + nchilds * sizeof(np));
-
- np->code = kp->code;
- np->nchilds = nchilds;
+ np = xmalloc(sizeof(*np));
+ np->op = op;
np->type = tp;
- np->typeop = tp->op;
- np->b.symbol = np->b.lvalue = 0;
+ np->sym = NULL;
+ np->constant = np->symbol = np->lvalue = 0;
+ np->left = left;
+ np->rigth = rigth;
+ return np;
+}
- switch (kp->unode) {
- case TYP:
- np->u.type = va_arg(va, Type *);
- break;
- case SYM:
- np->u.sym = va_arg(va, Symbol *);
- np->b.symbol = 1;
- np->b.constant = 1;
- break;
- case OP:
- np->u.op = va_arg(va, int);
- break;
- }
+Node *
+symbol(Symbol *sym)
+{
+ Node *np;
- for (i = 0; i < nchilds; ++i)
- np->childs[i] = va_arg(va, Node *);
-
- va_end(va);
+ np = node(OSYM, sym->type, NULL, NULL);
+ np->symbol = 1;
+ np->constant = 1;
+ np->sym = sym;
return np;
}
--- a/cc1/expr.c
+++ b/cc1/expr.c
@@ -5,7 +5,8 @@
#include "../inc/cc.h"
#include "cc1.h"
-#define Q(sym) node(SYMBOL, inttype, (sym))
+#define BTYPE(np) ((np)->type->op)
+#define TYPE(tp) node(OTYP, (tp), NULL, NULL)
static Symbol *zero, *one;
@@ -38,7 +39,7 @@
if (r > RANK_UINT || tp == inttype || tp == uinttype)
return np;
tp = (r == RANK_UINT) ? uinttype : inttype;
- return node(CAST, tp, np);
+ return node(OCAST, tp, np, NULL);
}
static void
@@ -55,9 +56,9 @@
tp2 = np2->type;
if (tp1 != tp2) {
if ((n = tp1->n.rank - tp2->n.rank) > 0)
- np2 = node(CAST, tp1, np2);
+ np2 = node(OCAST, tp1, np2, NULL);
else if (n < 0)
- np1 = node(CAST, tp2, np1);
+ np1 = node(OCAST, tp2, np1, NULL);
}
*p1 = np1;
*p2 = np2;
@@ -66,7 +67,7 @@
static void
chklvalue(Node *np, Type *tp)
{
- if (!np->b.lvalue)
+ if (!np->lvalue)
error("lvalue required in operation");
if (np->type == voidtype)
error("invalid use of void expression");
@@ -75,11 +76,14 @@
Node *
eval(Node *np)
{
+ Node *p;
+
if (!np)
return NULL;
if (!ISNODELOG(np))
return np;
- return node(TERNARY, inttype, np, Q(one), Q(zero));
+ p = node(0, inttype, symbol(one), symbol(zero));
+ return node(OASK, inttype, np, p);
}
static Node *
@@ -87,10 +91,10 @@
{
np1 = eval(np1);
np2 = eval(np2);
- if (np1->typeop != INT || np2->typeop != INT)
+ if (BTYPE(np1) != INT || BTYPE(np2) != INT)
error("operator requires integer operands");
typeconv(&np1, &np2);
- return node(BINARY, np1->type, op, np1, np2);
+ return node(op, np1->type, np1, np2);
}
static Node *
@@ -97,11 +101,11 @@
numericaluop(char op, Node *np)
{
np = eval(np);
- switch (np->typeop) {
+ switch (BTYPE(np)) {
case INT: case FLOAT:
if (op == OADD)
return np;
- return node(UNARY, np->type, op, np);
+ return node(op, np->type, np, NULL);
default:
error("unary operator requires integer operand");
}
@@ -111,15 +115,15 @@
integeruop(char op, Node *np)
{
np = eval(np);
- if (np->typeop != INT)
+ if (BTYPE(np) != INT)
error("unary operator requires integer operand");
- return node(UNARY, np->type, op, np);
+ return node(op, np->type, np, NULL);
}
static Node *
decay(Node *np)
{
- return node(UNARY, mktype(np->type, PTR, 0, NULL), OADDR, np);
+ return node(OADDR, mktype(np->type, PTR, 0, NULL), np, NULL);
}
/*
@@ -130,11 +134,11 @@
{
if (eqtype(np->type, tp))
return np;
- switch (np->typeop) {
+ switch (BTYPE(np)) {
case ENUM: case INT: case FLOAT:
switch (tp->op) {
case PTR:
- if (!iscast || np->typeop == FLOAT)
+ if (!iscast || BTYPE(np) == FLOAT)
return NULL;
/* PASSTHROUGH */
case INT: case FLOAT: case ENUM: case VOID:
@@ -167,7 +171,7 @@
default:
return NULL;
}
- return node(CAST, tp, np);
+ return node(OCAST, tp, np, NULL);
}
static Node *
@@ -177,21 +181,21 @@
Node *size;
tp = np1->type;
- size = node(SIZEOFCODE, inttype, tp->type);
- if (np2->typeop == ARY)
+ size = node(OSIZE, inttype, TYPE(tp->type), NULL);
+ if (BTYPE(np2) == ARY)
np2 = decay(np2);
- if (op == OSUB && np2->typeop == PTR) {
+ if (op == OSUB && BTYPE(np2) == PTR) {
if (tp != np2->type)
goto incorrect;
- np1 = node(BINARY, inttype, OSUB, np1, np2);
- return node(BINARY, inttype, ODIV, np1, size);
+ np1 = node(OSUB, inttype, np1, np2);
+ return node(ODIV, inttype, np1, size);
}
- if (np2->typeop != INT)
+ if (BTYPE(np2) != INT)
goto incorrect;
- np2 = node(CAST, tp, promote(np2));
- np2 = node(BINARY, tp, OMUL, np2, size);
- return node(BINARY, tp, op, np1, np2);
+ np2 = node(OCAST, tp, promote(np2), NULL);
+ np2 = node(OMUL, tp, np2, size);
+ return node(op, tp, np1, np2);
incorrect:
error("incorrect arithmetic operands");
@@ -202,9 +206,9 @@
{
np1 = eval(np1);
np2 = eval(np2);
- switch (np1->typeop) {
+ switch (BTYPE(np1)) {
case INT: case FLOAT:
- switch (np2->typeop) {
+ switch (BTYPE(np2)) {
case INT: case FLOAT:
typeconv(&np1, &np2);
break;
@@ -226,22 +230,27 @@
error("incorrect arithmetic operands");
}
- return node(BINARY, np1->type, op, np1, np2);
+ return node(op, np1->type, np1, np2);
}
static Node *
pcompare(char op, Node *np1, Node *np2)
{
- if (np2->typeop == INT && np2->b.symbol && np2->u.sym->u.i == 0) {
- np2 = node(CAST, pvoidtype, np2);
- } else if (np2->typeop != PTR) {
+ switch (BTYPE(np2)) {
+ case INT:
+ if (np2->symbol && np2->sym->u.i == 0)
+ np2 = node(OCAST, pvoidtype, np2, NULL);
+ break;
+ case PTR:
+ if (np1->type != np2->type)
+ warn(options.pcompare,
+ "comparision between different pointer types");
+ break;
+ default:
error("incompatibles type in comparision");
- } else {
- warn(options.pcompare,
- "comparision between different pointer types");
}
- return node(BINARY, np1->type, op, np1, np2);
+ return node(op, np1->type, np1, np2);
}
static Node *
@@ -249,9 +258,9 @@
{
np1 = eval(np1);
np2 = eval(np2);
- switch (np1->typeop) {
+ switch (BTYPE(np1)) {
case INT: case FLOAT:
- switch (np1->typeop) {
+ switch (BTYPE(np1)) {
case INT: case FLOAT:
typeconv(&np1, &np2);
break;
@@ -272,7 +281,7 @@
error("incompatibles type in comparision");
}
- return node(BINARY, inttype, op, np1, np2);
+ return node(op, inttype, np1, np2);
}
static Node *
@@ -283,7 +292,7 @@
return np;
}
- return compare(ONE ^ neg, np, Q(zero));
+ return compare(ONE ^ neg, np, symbol(zero));
}
static Node *
@@ -291,7 +300,7 @@
{
np1 = exp2cond(np1, 0);
np2 = exp2cond(np2, 0);
- return node(BINARY, inttype, op, np1, np2);
+ return node(op, inttype, np1, np2);
}
static Node *
@@ -300,7 +309,7 @@
extern uint8_t lex_ns;
Symbol *sym;
- switch (np->typeop) {
+ switch (BTYPE(np)) {
case STRUCT: case UNION:
lex_ns = np->type->ns;
next();
@@ -310,7 +319,7 @@
error("incorrect field in struct/union");
lex_ns = NS_IDEN;
next();
- return node(FIELD, sym->type, sym, np);
+ return node(OFIELD, sym->type, symbol(sym), np);
default:
error("struct or union expected");
}
@@ -321,14 +330,14 @@
{
Type *tp;
- if (np1->typeop != INT && np2->typeop != INT)
+ if (BTYPE(np1) != INT && BTYPE(np2) != INT)
error("array subscript is not an integer");
np1 = arithmetic(OADD, np1, np2);
tp = np1->type;
if (tp->op != PTR)
error("subscripted value is neither array nor pointer nor vector");
- np1 = node(UNARY, tp->type, OPTR, np1);
- np1->b.lvalue = 1;
+ np1 = node(OPTR, tp->type, np1, NULL);
+ np1->lvalue = 1;
return np1;
}
@@ -337,7 +346,7 @@
{
if (ISNODECMP(np))
return np;
- return compare(ONE, np, Q(zero));
+ return compare(ONE, np, symbol(zero));
}
static Node *
@@ -351,7 +360,7 @@
if ((np2 = convert(np2, np1->type, 0)) == NULL)
error("incompatible types when assigning");
}
- return node(BINARY, np1->type, op, np1, np2);
+ return node(op, np1->type, np1, np2);
}
static Node *
@@ -362,14 +371,14 @@
chklvalue(np, np->type);
- switch (np->typeop) {
+ switch (BTYPE(np)) {
case PTR:
if (!tp->defined)
error("invalid use of indefined type");
- inc = node(SIZEOFCODE, inttype, tp->type);
+ inc = node(OSIZE, inttype, TYPE(tp->type), NULL);
break;
case INT: case FLOAT:
- inc = Q(one);
+ inc = symbol(one);
break;
default:
error("incorrect type in arithmetic operation");
@@ -380,22 +389,22 @@
static Node *
address(char op, Node *np)
{
- if (!np->b.lvalue)
+ if (!np->lvalue)
error("lvalue required in unary expression");
- if (np->b.symbol && np->u.sym->isregister)
+ if (np->symbol && np->sym->isregister)
error("address of register variable '%s' requested", yytext);
- return node(UNARY, mktype(np->type, PTR, 0, NULL), op, np);
+ return node(op, mktype(np->type, PTR, 0, NULL), np, NULL);
}
static Node *
content(char op, Node *np)
{
- switch (np->typeop) {
+ switch (BTYPE(np)) {
case ARY: case FTN:
np = decay(np);
case PTR:
- np = node(UNARY, np->type, op, np);
- np->b.lvalue = 1;
+ np = node(op, np->type->type, np, NULL);
+ np->lvalue = 1;
return np;
default:
error("invalid argument of unary '*'");
@@ -405,7 +414,7 @@
static Node *
negation(char op, Node *np)
{
- switch (np->typeop) {
+ switch (BTYPE(np)) {
case FTN: case ARY:
np = decay(np);
case INT: case FLOAT: case PTR:
@@ -428,10 +437,10 @@
case STRING: case CONSTANT: case IDEN:
if ((sym = yylval.sym) == NULL)
error("'%s' undeclared", yytext);
- np = node(SYMBOL, yylval.sym->type, yylval.sym);
+ np = symbol(yylval.sym);
if (yytoken == IDEN) {
- np->b.lvalue = 1;
- np->b.constant = 0;
+ np->lvalue = 1;
+ np->constant = 0;
}
next();
break;
@@ -544,7 +553,7 @@
case SIZEOF:
next();
tp = (yytoken == '(') ? sizeexp() : typeof(unary());
- return node(SIZEOFCODE, inttype, tp);
+ return node(OSIZE, inttype, TYPE(tp), NULL);
case INC: case DEC:
op = (yytoken == INC) ? OA_ADD : OA_SUB;
next();
@@ -584,7 +593,7 @@
unexpected();
if ((np2 = convert(np1, tp, 1)) == NULL)
error("bad type convertion requested");
- np2->b.lvalue = np1->b.lvalue;
+ np2->lvalue = np1->lvalue;
}
break;
default:
@@ -747,17 +756,21 @@
static Node *
ternary(void)
{
- Node *np, *ifyes, *ifno;
+ Node *cond;
- np = or();
+ cond = or();
while (accept('?')) {
+ Node *ifyes, *ifno, *np;
+
+ cond = exp2cond(cond, 0);
ifyes = promote(expr());
expect(':');
ifno = promote(ternary());
typeconv(&ifyes, &ifno);
- np = node(TERNARY, ifyes->type, np, ifyes, ifno);
+ np = node(0, ifyes->type, ifyes, ifno);
+ cond = node(OASK, np->type, cond, np);
}
- return np;
+ return cond;
}
static Node *
@@ -796,7 +809,7 @@
np1 = assign();
while (accept(',')) {
np2 = assign();
- np1 = node(BINARY, np2->type, OCOMMA, np1, np2);
+ np1 = node(OCOMMA, np2->type, np1, np2);
}
return np1;