ref: 4f18f449b7ddb35be623af059e5e8a570c60ed15
parent: c73066ae16b32b24682b0e4fe6fe651f8779142d
parent: 62155438ef96682214a7ef7160c2b493b22ea5f6
author: Roberto E. Vargas Caballero <[email protected]>
date: Fri Aug 12 05:06:43 EDT 2016
Merge branch 'master' into qbe
--- a/README
+++ b/README
@@ -63,3 +63,11 @@
problems without this complexity (and they are the more usual
way of writing such code).
+- Definition of variables with incomplete type
+ ---------------------------------------------
+
+C89 allows the definition of variables with incomplete type that
+have external linkage and file scope. The type of the variable
+is the composition of all the definitions find in the file. The exact
+rules are a bit complex (3.7.2), and SCC ignores them at this moment
+and it does not allow any definition of variables with incomplete type.
--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -200,6 +200,7 @@
OBAND,
OBXOR,
OBOR,
+ OSNEG,
ONEG,
OCPL,
OAND,
@@ -349,7 +350,7 @@
extern void cpperror(char *fmt, ...);
/* types.c */
-extern int eqtype(Type *tp1, Type *tp2);
+extern int eqtype(Type *tp1, Type *tp2, int eqflag);
extern Type *ctype(unsigned type, unsigned sign, unsigned size);
extern Type *mktype(Type *tp, int op, TINT nelem, Type *data[]);
extern Type *duptype(Type *base);
@@ -420,7 +421,7 @@
extern int expand(char *begin, Symbol *sym);
extern void incdir(char *dir);
extern void outcpp(void);
-extern void defdefine(char *macro, char *val);
+extern void defdefine(char *macro, char *val, char *source);
extern void undefmacro(char *s);
/*
--- a/cc1/code.c
+++ b/cc1/code.c
@@ -50,7 +50,8 @@
[OA_XOR] = ":^",
[OA_OR] = ":|",
[OADDR] = "'",
- [ONEG] = "_",
+ [OSNEG] = "_",
+ [ONEG] = "n",
[OCPL] = "~",
[OAND] = "a",
[OOR] = "o",
@@ -104,6 +105,7 @@
[OA_XOR] = emitbin,
[OA_OR] = emitbin,
[OADDR] = emitbin,
+ [OSNEG] = emitbin,
[ONEG] = emitbin,
[OCPL] = emitbin,
[OAND] = emitbin,
--- a/cc1/cpp.c
+++ b/cc1/cpp.c
@@ -23,7 +23,7 @@
int disexpand;
void
-defdefine(char *macro, char *val)
+defdefine(char *macro, char *val, char *source)
{
char *def, *fmt = "#define %s %s";
@@ -32,7 +32,7 @@
def = xmalloc(strlen(fmt) + strlen(macro) + strlen(val));
sprintf(def, fmt, macro, val);
- allocinput("command-line", NULL, def);
+ allocinput(source, NULL, def);
input->nline = ++ncmdlines;
cpp();
delinput();
@@ -78,17 +78,17 @@
tm = localtime(&t);
strftime(sdate, sizeof(sdate), "\"%b %d %Y\"", tm);
strftime(stime, sizeof(stime), "\"%H:%M:%S\"", tm);
- defdefine("__DATE__", sdate);
- defdefine("__TIME__", stime);
- defdefine("__STDC_VERSION__", "199409L");
- defdefine("__LINE__", NULL);
- defdefine("__FILE__", NULL);
+ defdefine("__DATE__", sdate, "built-in");
+ defdefine("__TIME__", stime, "built-in");
+ defdefine("__STDC_VERSION__", "199409L", "built-in");
+ defdefine("__LINE__", NULL, "built-in");
+ defdefine("__FILE__", NULL, "built-in");
symline = lookup(NS_CPP, "__LINE__");
symfile = lookup(NS_CPP, "__FILE__");
for (bp = list; *bp; ++bp)
- defdefine(*bp, NULL);
+ defdefine(*bp, "1", "built-in");
ncmdlines = 0;
}
@@ -652,8 +652,10 @@
{
int status;
- if (cppctx == 0)
- error("#else without #ifdef/ifndef");
+ if (cppctx == 0) {
+ cpperror("#else without #ifdef/ifndef");
+ return;
+ }
status = (ifstatus[cppctx-1] ^= 1);
cppoff += (status) ? -1 : 1;
--- a/cc1/decl.c
+++ b/cc1/decl.c
@@ -118,13 +118,15 @@
}
static int
-empty(Symbol *sym, Type *tp)
+empty(Symbol *sym, Type *tp, int param)
{
if (!sym->name) {
sym->type = tp;
switch (tp->op) {
default:
- warn("empty declaration");
+ /* warn if it is not a parameter */
+ if (!param)
+ warn("empty declaration");
case STRUCT:
case UNION:
case ENUM:
@@ -175,7 +177,7 @@
errorp("incorrect function type for a function parameter");
return NULL;
}
- if (!empty(sym, tp)) {
+ if (!empty(sym, tp, 1)) {
Symbol *p = install(NS_IDEN, sym);
if (!p && !(funtp->prop & TK_R)) {
errorp("redefinition of parameter '%s'", name);
@@ -615,7 +617,7 @@
TINT n = structp->n.elem;
int err = 0;
- if (empty(sym, tp))
+ if (empty(sym, tp, 0))
return sym;
if (tp->op == FTN) {
errorp("invalid type in struct/union");
@@ -662,7 +664,7 @@
int flags;
char *name = sym->name;
- if (!eqtype(sym->type, tp)) {
+ if (!eqtype(sym->type, tp, 1)) {
errorp("conflicting types for '%s'", name);
return sym;
}
@@ -724,7 +726,7 @@
int sclass = dcl->sclass;
char *name = sym->name;
- if (empty(sym, tp))
+ if (empty(sym, tp, 0))
return sym;
/* TODO: Add warning about ANSI limits */
--- a/cc1/expr.c
+++ b/cc1/expr.c
@@ -37,22 +37,6 @@
return 0;
}
-int
-isnodecmp(int op)
-{
- switch (op) {
- case OEQ:
- case ONE:
- case OLT:
- case OGE:
- case OLE:
- case OGT:
- return 1;
- default:
- return 0;
- }
-}
-
static Node *
promote(Node *np)
{
@@ -144,9 +128,6 @@
static Node *
chkternary(Node *yes, Node *no)
{
- yes = decay(yes);
- no = decay(no);
-
/*
* FIXME:
* We are ignoring type qualifiers here,
@@ -154,7 +135,7 @@
* take a look to 6.5.15
*/
- if (!eqtype(yes->type, no->type)) {
+ if (!eqtype(yes->type, no->type, 1)) {
if ((yes->type->prop & TARITH) && (no->type->prop & TARITH)) {
arithconv(&yes, &no);
} else if (yes->type->op != PTR && no->type->op != PTR) {
@@ -181,7 +162,7 @@
if (null(no))
no = convert(no, yes->type, 0);
- if (!eqtype(yes->type, no->type))
+ if (!eqtype(yes->type, no->type, 1))
goto wrong_type;
}
}
@@ -254,7 +235,7 @@
if (!(np->type->prop & TARITH))
error("unary operator requires numerical operand");
np = promote(np);
- if (op == ONEG && np->op == ONEG)
+ if (op == OSNEG && np->op == OSNEG)
return np->left;
if (op == OADD)
return np;
@@ -266,7 +247,7 @@
{
Type *oldtp = np->type;
- if (eqtype(newtp, oldtp))
+ if (eqtype(newtp, oldtp, 0))
return np;
switch (oldtp->op) {
@@ -295,7 +276,8 @@
return NULL;
break;
case PTR:
- if (iscast ||
+ if (eqtype(newtp, oldtp, 1) ||
+ iscast ||
newtp == pvoidtype || oldtp == pvoidtype) {
np->type = newtp;
return np;
@@ -318,7 +300,12 @@
if (lp->type->op != PTR)
XCHG(lp, rp, np);
+ tp = rp->type;
+ if (tp->op == PTR && !(tp->type->prop & TDEFINED))
+ goto incomplete;
tp = lp->type;
+ if (!(tp->type->prop & TDEFINED))
+ goto incomplete;
size = sizeofnode(tp->type);
if (op == OSUB && BTYPE(rp) == PTR) {
@@ -336,9 +323,13 @@
return simplify(OADD, tp, lp, rp);
+incomplete:
+ errorp("invalid use of undefined type");
+ return lp;
incorrect:
errorp("incorrect arithmetic operands");
- return node(OADD, tp, lp, rp);
+ return lp;
+
}
static Node *
@@ -371,7 +362,7 @@
err = 1;
rp = convert(rp, pvoidtype, 1);
} else if (rp->type->op == PTR) {
- if (!eqtype(lp->type, rp->type))
+ if (!eqtype(lp->type, rp->type, 1))
err = 1;
} else {
err = 1;
@@ -386,9 +377,6 @@
{
Type *ltp, *rtp;
- lp = decay(lp);
- rp = decay(rp);
-
ltp = lp->type;
rtp = rp->type;
@@ -409,8 +397,6 @@
negop(int op)
{
switch (op) {
- case OAND: return OOR;
- case OOR: return OAND;
case OEQ: return ONE;
case ONE: return OEQ;
case OLT: return OGE;
@@ -425,11 +411,32 @@
Node *
negate(Node *np)
{
- if (np->op == OSYM) {
+ int op = np->op;
+
+ switch (np->op) {
+ case OSYM:
assert(np->flags&NCONST && np->type->prop&TINTEGER);
np->sym = (np->sym->u.i) ? zero : one;
- } else {
- np->op = negop(np->op);
+ break;
+ case OOR:
+ case OAND:
+ if (np->op == ONEG) {
+ Node *new = np->left;
+ free(np);
+ return new;
+ }
+ np = node(ONEG, inttype, np, NULL);
+ break;
+ case OEQ:
+ case ONE:
+ case OLT:
+ case OGE:
+ case OLE:
+ case OGT:
+ np->op = negop(op);
+ break;
+ default:
+ abort();
}
return np;
@@ -438,14 +445,23 @@
static Node *
exp2cond(Node *np, char neg)
{
- np = decay(np);
if (np->type->prop & TAGGREG) {
errorp("used struct/union type value where scalar is required");
- np = constnode(zero);
+ return constnode(zero);
}
- if (isnodecmp(np->op))
+ switch (np->op) {
+ case OOR:
+ case OAND:
+ case OEQ:
+ case ONE:
+ case OLT:
+ case OGE:
+ case OLE:
+ case OGT:
return (neg) ? negate(np) : np;
- return compare((neg) ? OEQ : ONE, np, constnode(zero));
+ default:
+ return compare((neg) ? OEQ : ONE, np, constnode(zero));
+ }
}
static Node *
@@ -491,11 +507,9 @@
static Node *
content(char op, Node *np)
{
- np = decay(np);
- switch (BTYPE(np)) {
- case ARY:
- case FTN:
- case PTR:
+ if (BTYPE(np) != PTR) {
+ errorp("invalid argument of memory indirection");
+ } else {
if (np->op == OADDR) {
Node *new = np->left;
new->type = np->type->type;
@@ -505,10 +519,8 @@
np = node(op, np->type->type, np, NULL);
}
np->flags |= NLVAL;
- return np;
- default:
- error("invalid argument of memory indirection");
}
+ return np;
}
static Node *
@@ -519,7 +531,7 @@
if (!(lp->type->prop & TINTEGER) && !(rp->type->prop & TINTEGER))
error("array subscript is not an integer");
- np = arithmetic(OADD, decay(lp), decay(rp));
+ np = arithmetic(OADD, lp, rp);
tp = np->type;
if (tp->op != PTR)
errorp("subscripted value is neither array nor pointer");
@@ -529,7 +541,7 @@
static Node *
assignop(char op, Node *lp, Node *rp)
{
- if ((rp = convert(decay(rp), lp->type, 0)) == NULL) {
+ if ((rp = convert(rp, lp->type, 0)) == NULL) {
errorp("incompatible types when assigning");
return lp;
}
@@ -549,6 +561,10 @@
if (!(tp->prop & TDEFINED)) {
errorp("invalid use of undefined type");
return np;
+ } else if (tp->op == PTR && !(tp->type->prop & TDEFINED)) {
+ errorp("%s of pointer to an incomplete type",
+ (op == OINC) ? "increment" : "decrement");
+ return np;
} else if (tp->prop & TARITH) {
inc = constnode(one);
} else if (tp->op == PTR) {
@@ -565,16 +581,26 @@
{
Node *new;
- if (BTYPE(np) != FTN) {
- chklvalue(np);
- if (np->sym && (np->sym->flags & SREGISTER))
- errorp("address of register variable '%s' requested", yytext);
- if (np->op == OPTR) {
- Node *new = np->left;
- free(np);
- return new;
- }
+ /*
+ * ansi c accepts & applied to a function name, and it generates
+ * a function pointer
+ */
+ if (np->op == OSYM) {
+ if (np->type->op == FTN)
+ return decay(np);
+ if (np->type->op == ARY)
+ goto dont_check_lvalue;
}
+ chklvalue(np);
+
+dont_check_lvalue:
+ if (np->sym && (np->sym->flags & SREGISTER))
+ errorp("address of register variable '%s' requested", yytext);
+ if (np->op == OPTR) {
+ Node *new = np->left;
+ free(np);
+ return new;
+ }
new = node(op, mktype(np->type, PTR, 0, NULL), np, NULL);
if (np->sym && np->sym->flags & (SGLOBAL|SLOCAL|SPRIVATE))
@@ -585,7 +611,6 @@
static Node *
negation(char op, Node *np)
{
- np = decay(np);
if (!(np->type->prop & TARITH) && np->type->op != PTR) {
errorp("invalid argument of unary '!'");
freetree(np);
@@ -636,7 +661,7 @@
sym->flags |= SHASINIT;
emit(ODECL, sym);
emit(OINIT, np);
- np = decay(varnode(sym));
+ np = varnode(sym);
next();
break;
case CONSTANT:
@@ -688,7 +713,7 @@
toomany = 0;
do {
- arg = decay(assign());
+ arg = assign();
argtype = *targs;
if (argtype == ellipsistype) {
n = 0;
@@ -727,43 +752,8 @@
return node(OCALL, rettype, np, par);
}
-static Node *
-postfix(Node *lp)
-{
- Node *rp;
+static Node *unary(int);
- if (!lp)
- lp = primary();
- for (;;) {
- switch (yytoken) {
- case '[':
- next();
- rp = expr();
- lp = array(lp, rp);
- expect(']');
- break;
- case DEC:
- case INC:
- lp = incdec(lp, (yytoken == INC) ? OINC : ODEC);
- next();
- break;
- case INDIR:
- lp = content(OPTR, lp);
- case '.':
- lp = field(lp);
- break;
- case '(':
- lp = arguments(lp);
- lp->flags |= NEFFECT;
- break;
- default:
- return lp;
- }
- }
-}
-
-static Node *unary(void);
-
static Type *
typeof(Node *np)
{
@@ -788,7 +778,7 @@
tp = typename();
break;
default:
- tp = typeof(unary());
+ tp = typeof(unary(0));
break;
}
expect(')');
@@ -795,19 +785,68 @@
return tp;
}
-static Node *cast(void);
+static Node *
+postfix(Node *lp)
+{
+ Node *rp;
+ for (;;) {
+ switch (yytoken) {
+ case '[':
+ case DEC:
+ case INC:
+ case INDIR:
+ case '.':
+ case '(':
+ lp = decay(lp);
+ switch (yytoken) {
+ case '[':
+ next();
+ rp = expr();
+ expect(']');
+ lp = array(lp, rp);
+ break;
+ case DEC:
+ case INC:
+ lp = incdec(lp, (yytoken == INC) ? OINC : ODEC);
+ next();
+ break;
+ case INDIR:
+ lp = content(OPTR, lp);
+ case '.':
+ lp = field(lp);
+ break;
+ case '(':
+ lp = arguments(lp);
+ lp->flags |= NEFFECT;
+ break;
+ }
+ break;
+ default:
+ return lp;
+ }
+ }
+}
+
+static Node *cast(int);
+
static Node *
-unary(void)
+unary(int needdecay)
{
- Node *(*fun)(char, Node *);
+ Node *(*fun)(char, Node *), *np;
char op;
Type *tp;
switch (yytoken) {
+ case '!': op = 0; fun = negation; break;
+ case '+': op = OADD; fun = numericaluop; break;
+ case '-': op = OSNEG; fun = numericaluop; break;
+ case '~': op = OCPL; fun = integeruop; break;
+ case '&': op = OADDR; fun = address; break;
+ case '*': op = OPTR; fun = content; break;
case SIZEOF:
next();
- tp = (yytoken == '(') ? sizeexp() : typeof(unary());
+ tp = (yytoken == '(') ? sizeexp() : typeof(unary(0));
if (!(tp->prop & TDEFINED))
errorp("sizeof applied to an incomplete type");
return sizeofnode(tp);
@@ -815,22 +854,24 @@
case DEC:
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;
- default: return postfix(NULL);
+ np = incdec(unary(1), op);
+ goto chk_decay;
+ default:
+ np = postfix(primary());
+ goto chk_decay;
}
next();
- return (*fun)(op, cast());
+ np = (*fun)(op, cast(op != OADDR));
+
+chk_decay:
+ if (needdecay)
+ np = decay(np);
+ return np;
}
static Node *
-cast(void)
+cast(int needdecay)
{
Node *lp, *rp;
Type *tp;
@@ -837,7 +878,7 @@
static int nested;
if (!accept('('))
- return unary();
+ return unary(needdecay);
switch (yytoken) {
case TQUALIFIER:
@@ -852,7 +893,7 @@
case ARY:
error("cast specifies an array type");
default:
- lp = cast();
+ lp = cast(needdecay);
if ((rp = convert(lp, tp, 1)) == NULL)
error("bad type conversion requested");
rp->flags &= ~NLVAL;
@@ -879,7 +920,7 @@
Node *np, *(*fun)(char, Node *, Node *);
char op;
- np = cast();
+ np = cast(1);
for (;;) {
switch (yytoken) {
case '*': op = OMUL; fun = arithmetic; break;
@@ -888,7 +929,7 @@
default: return np;
}
next();
- np = (*fun)(op, np, cast());
+ np = (*fun)(op, np, cast(1));
}
}
--- a/cc1/fold.c
+++ b/cc1/fold.c
@@ -188,7 +188,8 @@
case OLE: i = l <= r; break;
case OEQ: i = l == r; break;
case ONE: i = l != r; break;
- case ONEG: i = -l; break;
+ case ONEG: i = !l; break;
+ case OSNEG: i = -l; break;
case OCPL: i = ~l; break;
default: return 0;
}
@@ -213,7 +214,8 @@
case OBAND: u = l & r; break;
case OBXOR: u = l ^ r; break;
case OBOR: u = l | r; break;
- case ONEG: u = -l; break;
+ case ONEG: u = !l; break;
+ case OSNEG: u = -l; break;
case OCPL: u = ~l; break;
case OAND: i = l && r; goto sign;
case OOR: i = l || r; goto sign;
--- a/cc1/init.c
+++ b/cc1/init.c
@@ -134,7 +134,7 @@
return np;
}
- if (eqtype(tp, np->type))
+ if (eqtype(tp, np->type, 1))
return np;
if ((aux = convert(decay(np), tp, 0)) != NULL)
return aux;
--- a/cc1/main.c
+++ b/cc1/main.c
@@ -38,7 +38,7 @@
else
p = "1";
- defdefine(macro, p);
+ defdefine(macro, p, "command-line");
}
static void
--- a/cc1/tests/test001.c
+++ b/cc1/tests/test001.c
@@ -9,13 +9,13 @@
G6 I F "main
{
\
-V8 K #N13
-Y7 V8 " (
+V9 K #N13
+Y8 V9 " (
#"hello world
#K0A
#K00
)
- X4 Y7 'P pP cI
+ X4 Y8 'P pP cI
h #I0
}
*/
--- /dev/null
+++ b/cc1/tests/test065.c
@@ -1,0 +1,66 @@
+/* See LICENSE file for copyright and license details. */
+
+/*
+name: TEST065
+description: Test decay mixed with * operators
+error:
+test065.c:65: error: decrement of pointer to an incomplete type
+test065.c:65: error: invalid use of undefined type
+test065.c:66: warning: 'argv' defined but not used
+output:
+G7 I F "main
+{
+A1 I "argc
+A5 P "argv
+\
+V8 I #N1
+A9 V8 "v
+A12 P "p
+A14 P "f1
+A15 P "f2
+ A9 #I0 :I
+ A12 A9 'P :P
+ A14 G7 'P :P
+ A15 G7 'P :P
+ y L18 A1 #I0 !I
+ h #I1
+L18
+ y L19 G7 #I0 pI #P0 pP cI #I0 =I
+ h #I2
+L19
+ y L20 A14 @F #I0 pI #P0 pP cI #I0 =I
+ h #I3
+L20
+ y L21 A15 @F #I0 pI #P0 pP cI #I0 =I
+ h #I4
+L21
+ y L22 A12 @I #I0 !I
+ h #I0
+L22
+*/
+
+int
+main(int argc, char *argv[])
+{
+ int v[1];
+ int (*p)[];
+ int (*f1)(int ,char *[]);
+ int (*f2)(int ,char *[]);
+
+ v[0] = 0;
+ p = &v;
+ f1 = &main;
+ f2 = main;
+ if (argc == 0)
+ return 1;
+ if ((****main)(0, 0))
+ return 2;
+ if ((****f1)(0, 0))
+ return 3;
+ if ((****f2)(0, 0))
+ return 4;
+ if (!(*p)[0])
+ return 0;
+
+ return (*++p)[0] || p[1][0];
+}
--- a/cc1/types.c
+++ b/cc1/types.c
@@ -296,7 +296,7 @@
t = (op ^ (uintptr_t) tp >> 3) & NR_TYPE_HASH-1;
tbl = &typetab[t];
for (bp = *tbl; bp; bp = bp->next) {
- if (eqtype(bp, &type) && op != STRUCT && op != UNION) {
+ if (eqtype(bp, &type, 0) && op != STRUCT && op != UNION) {
/*
* pars was allocated by the caller
* but the type already exists, so
@@ -314,7 +314,7 @@
}
int
-eqtype(Type *tp1, Type *tp2)
+eqtype(Type *tp1, Type *tp2, int equiv)
{
TINT n;
Type **p1, **p2;
@@ -333,16 +333,18 @@
return 0;
p1 = tp1->p.pars, p2 = tp2->p.pars;
for (n = tp1->n.elem; n > 0; --n) {
- if (!eqtype(*p1++, *p2++))
+ if (!eqtype(*p1++, *p2++, equiv))
return 0;
}
goto check_base;
case ARY:
+ if (equiv && (tp1->n.elem == 0 || tp2->n.elem == 0))
+ goto check_base;
if (tp1->n.elem != tp2->n.elem)
return 0;
case PTR:
check_base:
- return eqtype(tp1->type, tp2->type);
+ return eqtype(tp1->type, tp2->type, equiv);
case VOID:
case ENUM:
return 0;
--- a/cc2.old/Makefile
+++ /dev/null
@@ -1,23 +1,0 @@
-.POSIX:
-
-include ../config.mk
-
-OBJS = main.o parser.o cgen.o code.o optm.o peep.o
-
-all: cc2
-
-
-$(OBJS): ../inc/cc.h ../inc/sizes.h cc2.h
-main.o: error.h
-
-error.h: cc2.h
- rm -f $@; trap 'rm -f $$$$.h' EXIT INT QUIT
- awk -f generror cc2.h > $$$$.h && mv $$$$.h $@
-
-cc2: $(OBJS) ../lib/libcc.a
- $(CC) $(LDFLAGS) $(OBJS) ../lib/libcc.a -o $@
-
-clean:
- rm -f $(OBJS)
- rm -f cc2 error.h
-
--- a/cc2.old/cast.patch
+++ /dev/null
@@ -1,61 +1,0 @@
-diff --git a/cc2/cgen.c b/cc2/cgen.c
-index be4ff41..8839505 100644
---- a/cc2/cgen.c
-+++ b/cc2/cgen.c
-@@ -449,16 +449,50 @@ cast(Node *np)
- {
- Node *lp = np->left;
- uint8_t reg;
-+ int8_t delta;
-
-- if (lp->type.size != np->type.size)
-+ swtich (lp->type.size) {
-+ case 1:
-+ switch (np->type.size) {
-+ case 1:
-+ break;
-+ case 2:
-+ if (lp->op != REG)
-+ move(lp, np);
-+ np->reg = reg = lp->reg;
-+ if (lp->sign && np->sign) {
-+ code(BIT, lp, imm(7));
-+ code(JRZ, .., ..);
-+ code(LDI, regs[upper[reg]], imm(-1));
-+ code(JR, ..., ...);
-+ }
-+ reguse[pair[reg]] = reguse[reg] = np;
-+ code(LDI, regs[lower[reg]], imm(0));
-+ break;
-+ default:
-+ abort();
-+ }
-+ break;
-+ case 2:
-+ switch (np->type.size) {
-+ case 1:
-+ if (lp->op == REG) {
-+ reguse[upper[reg]] = NULL;
-+ reg = lower[reg];
-+ np->reg = reg;
-+ reguse[pair[reg]] = reguse[reg] = np;
-+ }
-+ break;
-+ case 2:
-+ break;
-+ default:
-+ abort();
-+ }
-+ default:
- abort();
-+ }
- lp->used = 1;
- np->sym = lp->sym;
-- if ((np->op = lp->op) == REG) {
-- reg = lp->reg;
-- np->reg = reg;
-- reguse[pair[reg]] = reguse[reg] = np;
-- }
- }
-
- static void (*opnodes[])(Node *) = {
--- a/cc2.old/cc2.h
+++ /dev/null
@@ -1,179 +1,0 @@
-
-#define SIGNF 1
-#define INTF 2
-
-#define NONE 0
-#define AUTO 'A'
-#define REG 'R'
-#define MEM 'T'
-#define PAR 'P'
-#define CONST '#'
-#define INDEX 'I'
-#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 ORET 'y'
-
-#define ADDABLE 10
-
-
-typedef struct symbol Symbol;
-typedef struct node Node;
-typedef struct inst Inst;
-typedef struct addr Addr;
-typedef struct type Type;
-
-struct type {
- unsigned short size;
- uint8_t align;
- char letter;
- uint8_t flags;
-};
-
-struct symbol {
- unsigned short id;
- char *name;
- char kind;
- bool public : 1;
- bool extrn : 1;
- bool index : 1;
- union {
- /* TODO: Admit inmediate of other type */
- TINT imm;
- struct {
- Type type;
- char sclass;
- short off;
- } v;
- Inst *pc;
- struct {
- short locals;
- short params;
- Node **body;
- } f;
- } u;
-};
-
-struct node {
- uint8_t op;
- uint8_t subop;
- Type type;
- uint8_t complex;
- uint8_t addable;
- uint8_t reg;
- Symbol *sym;
- bool used : 1;
- struct node *left, *right;
-};
-
-
-struct addr {
- char kind;
- union {
- uint8_t reg;
- TINT i;
- Symbol *sym;
- } u;
-};
-
-struct inst {
- uint8_t op;
- Addr from, to;
- Symbol *label;
- Inst *next, *prev;
-};
-
-enum nerrors {
- EINTNUM, /* too much internal identifiers */
- EEXTNUM, /* too much external identifiers */
- EPARNUM, /* too much parameters */
- ENODEOV, /* node overflow */
- ESTACKO, /* stack overflow */
- ESTACKU, /* stack underflow */
- EEXPROV, /* expression overflow */
- ETYPERR, /* incorrect type in expression */
- EEXPBAL, /* expression not balanced */
- ESYNTAX, /* syntax error */
- ELNLINE, /* line too long */
- EFERROR, /* error reading from file:%s*/
- ENUMERR
-};
-
-enum {
- LDW,
- LDL,
- LDH,
- MOV,
- LDI,
- ADD,
- PUSH,
- POP,
- RET,
- NOP,
- INC,
- SUB,
- DEC,
- JP,
- AND,
- OR,
- XOR,
- CPL,
- NEG
-};
-
-enum {
- A = 1, B, C, D, E, H, L, IYL, IYH, NREGS,
- AF = NREGS, HL, DE, BC, IY, NPAIRS,
- SP = NPAIRS, IX
-};
-
-extern Symbol *curfun;
-extern Inst *prog, *pc;
-
-/* main.c */
-extern void error(unsigned nerror, ...);
-
-/* cgen.c */
-extern void addable(void);
-extern void generate(void);
-extern void apply(Node *(*fun)(Node *));
-
-/* parser.c */
-extern void parse(void);
-extern void prtree(Node *np);
-
-/* code.c */
-extern void code(uint8_t op, Node *to, Node *from);
-extern void inscode(uint8_t op, Addr *to, Addr *from);
-extern void writeout(void);
-extern void delcode(void);
-
-/* optm.c */
-extern void optimize(void);
-extern Node *imm(TINT i);
-
-/* peep.c */
-extern void peephole(void);
--- a/cc2.old/cgen.c
+++ /dev/null
@@ -1,602 +1,0 @@
-
-#include <assert.h>
-#include <inttypes.h>
-#include <stdlib.h>
-
-#include "../inc/cc.h"
-#include "cc2.h"
-
-static Symbol retlabel = {
- .kind = LABEL
-};
-
-static Node *reguse[NPAIRS];
-static uint8_t upper[] = {[DE] = D, [HL] = H, [BC] = B, [IY] = IYH};
-static uint8_t lower[] = {[DE] = E, [HL] = L, [BC] = C, [IY] = IYL};
-static uint8_t pair[] = {
- [A] = A,
- [H] = HL, [L] = HL, [HL] = HL,
- [B] = BC, [C] = BC, [BC] = BC,
- [D] = DE, [E] = DE, [DE] = DE,
- [IYL] = IY, [IYH] = IY, [IY] = IY
-};
-
-static Node regs[] = {
- [E] = {
- .op = REG,
- .reg = E
- },
- [D] = {
- .op = REG,
- .reg = D
- },
- [H] = {
- .op = REG,
- .reg = H
- },
- [L] = {
- .op = REG,
- .reg = L
- },
- [C] = {
- .op= REG,
- .reg = C
- },
- [B] = {
- .op= REG,
- .reg = B
- },
- [A] = {
- .op= REG,
- .reg = A
- },
- [IYL] = {
- .op = REG,
- .reg = IYL
- },
- [IYH] = {
- .op = REG,
- .reg = IYH
- },
- [DE] = {
- .op = REG,
- .reg = DE
- },
- [HL] = {
- .op = REG,
- .reg = HL
- },
- [BC] = {
- .op = REG,
- .reg = BC
- },
- [IX] = {
- .op = REG,
- .reg = IX
- },
- [IY] = {
- .op = REG,
- .reg = IY
- },
- [SP] = {
- .op = REG,
- .reg = SP
- }
-};
-
-static void moveto(Node *np, uint8_t reg);
-
-static void
-allocreg(Node *np)
-{
- static uint8_t reg8[] = {A, B, C, D, E, H, L, IYL, IY, 0};
- static uint8_t reg16[] = {BC, DE, IY, 0};
- Node *r;
- uint8_t *ary, *bp, c;
-
- switch (np->type.size) {
- case 1:
- ary = reg8;
- break;
- case 2:
- ary = reg16;
- break;
- default:
- abort();
- }
- for (bp = ary; c = *bp; ++bp) {
- r = reguse[c];
- if (!r || r->used) {
- moveto(np, c);
- return;
- }
- }
- /* TODO: What to do here? */
- abort();
-}
-
-static void
-spill(uint8_t reg)
-{
- Node *np, *r;
- Symbol *sym;
- uint8_t p, h, l;
-
- if ((np = reguse[reg]) == NULL)
- return;
- sym = np->sym;
- r = ®s[reg];
-
- switch (np->type.size) {
- case 1:
- if (sym) {
- code(LDL, np, r);
- np->op = sym->kind;
- } else {
- allocreg(np);
- }
- break;
- default:
- abort();
- }
-
- reguse[reg] = NULL;
- p = pair[reg];
- l = lower[p];
- h = upper[p];
- if (reg >= NREGS)
- reguse[l] = reguse[h] = NULL;
- else if (!reguse[l] && !reguse[h])
- reguse[p] = NULL;
-}
-
-static void
-moveto(Node *np, uint8_t reg)
-{
- Node *r = ®s[reg], *u = reguse[reg];
- char op = np->op;
-
- if (u) {
- Symbol *sym = np->sym;
- if (sym && sym == u->sym)
- return;
- else if (!np->used)
- spill(reg);
- }
-
- switch (np->type.size) {
- case 1:
- switch (op) {
- case MEM:
- case AUTO:
- code(LDL, r, np);
- break;
- case CONST:
- case INDEX:
- code(LDI, r, np);
- break;
- case REG:
- code(MOV, r, np);
- break;
- default:
- abort();
- }
- break;
- case 2:
- switch (op) {
- case CONST:
- code(LDL, r, np);
- break;
- case AUTO:
- code(LDL, ®s[lower[reg]], np);
- code(LDH, ®s[upper[reg]], np);
- break;
- default:
- abort();
- }
- reguse[upper[reg]] = reguse[lower[reg]] = np;
- break;
- default:
- abort();
- }
- reguse[pair[reg]] = reguse[reg] = np;
- np->op = REG;
- np->reg = reg;
-}
-
-static void
-accum(Node *np)
-{
- switch (np->type.size) {
- case 1:
- moveto(np, A);
- break;
- case 2:
- moveto(np, HL);
- break;
- default:
- abort();
- }
-}
-
-static void
-index(Node *np)
-{
- Node *u = reguse[HL];
- Symbol *sym;
-
- if (u && u->sym) {
- if (u->op == INDEX && np->sym == u->sym) {
- np->op = INDEX;
- return;
- } else {
- spill(HL);
- }
- }
- code(LDI, ®s[HL], np);
- if (sym = np->sym)
- sym->index = 1;
- np->op = INDEX;
- reguse[HL] = reguse[H] = reguse[L] = np;
-}
-
-static void
-move(Node *np, Node *parent)
-{
- assert(np->type.size == 1);
- switch (parent->op) {
- case OASSIG:
- allocreg(np);
- break;
- case ONEG:
- case OCPL:
- switch (np->op) {
- case REG:
- if (np->reg == A)
- break;
- /* PASSTHROUGH */
- case PAR:
- case AUTO:
- case CONST:
- case MEM:
- case INDEX:
- accum(np);
- break;
- default:
- abort();
- }
- break;
- case OADD:
- case OSUB:
- case OBAND:
- case OBOR:
- case OBXOR:
- switch (np->op) {
- case PAR:
- case AUTO:
- case CONST:
- case INDEX:
- case REG:
- return;
- case MEM:
- index(np);
- break;
- default:
- abort();
- }
- break;
- default:
- abort();
- }
-}
-
-static void
-conmute(Node *np)
-{
- Node *p, *q;
-
- p = np->left;
- q = np->right;
- np->left = q;
- np->right = p;
-}
-
-static void
-add(Node *np)
-{
- Node *lp = np->left, *rp = np->right, *a;
- uint8_t op;
-
- switch (np->type.size) {
- case 1:
- a = reguse[A];
- if (a == lp)
- goto update_a;
- if (a == rp)
- goto conmute1;
- if (lp->op == CONST) {
- accum(rp);
- goto conmute1;
- }
- accum(lp);
- goto update_a;
- conmute1:
- conmute(np);
- lp = np->left, rp = np->right;
- update_a:
- move(rp, np);
- switch (np->op) {
- case OADD:
- op = ADD;
- break;
- case OSUB:
- op = SUB;
- break;
- case OBAND:
- op = AND;
- break;
- case OBOR:
- op = OR;
- break;
- case OBXOR:
- op = XOR;
- break;
- default:
- abort();
- }
- code(op, lp, rp);
- lp->used = rp->used = 1;
- np->op = REG;
- np->reg = A;
- reguse[A] = np;
- break;
- default:
- abort();
- }
-}
-
-static void
-assign(Node *np)
-{
- Node *lp = np->left, *rp = np->right;
- Symbol *sym = lp->sym;
-
- switch (np->type.size) {
- case 1:
- switch (lp->op) {
- case MEM:
- if (sym && sym->index)
- lp->op = INDEX;
- /* PASSTROUGH */
- case INDEX:
- case AUTO:
- if (rp->op != REG)
- move(rp, np);
- lp->reg = rp->reg;
- code(LDL, lp, rp);
- break;
- case REG:
- code(MOV, lp, rp);
- break;
- default:
- abort();
- }
- break;
- default:
- abort();
- }
-
- np->op = REG;
- np->reg = lp->reg;
- np->sym = rp->sym = lp->sym;
- np->used = rp->used = lp->used = 1;
-}
-
-static void
-ret(Node *np)
-{
- static Node retnode = {
- .op = LABEL,
- .sym = &retlabel
- };
-
- if (np->left)
- accum(np->left);
- code(JP, &retnode, NULL);
-}
-
-static void
-nop(Node *np)
-{
-}
-
-static void
-cpl(Node *np)
-{
-
- Node *lp = np->left;
- uint8_t op;
-
- switch (np->type.size) {
- case 1:
- move(lp, np);
- switch (np->op) {
- case OCPL:
- op = CPL;
- break;
- case ONEG:
- op = NEG;
- break;
- default:
- abort();
- }
- code(op, lp, NULL);
- lp->used = 1;
- np->sym = lp->sym;
- np->reg = lp->reg;
- np->op = REG;
- reguse[A] = np;
- break;
- default:
- abort();
- }
-}
-
-static void
-cast(Node *np)
-{
- Node *lp = np->left;
- uint8_t reg;
-
- if (lp->type.size != np->type.size)
- abort();
- lp->used = 1;
- np->sym = lp->sym;
- if ((np->op = lp->op) == REG) {
- reg = lp->reg;
- np->reg = reg;
- reguse[pair[reg]] = reguse[reg] = np;
- }
-}
-
-static void (*opnodes[])(Node *) = {
- [OADD] = add,
- [OSUB] = add,
- [OASSIG] = assign,
- [ORET] = ret,
- [MEM] = nop,
- [REG] = nop,
- [AUTO] = nop,
- [CONST] = nop,
- [PAR] = nop,
- [OBOR] = add,
- [OBAND] = add,
- [OBXOR] = add,
- [OCPL] = cpl,
- [ONEG] = cpl,
- [OCAST] = cast
-};
-
-static void
-cgen(Node *np)
-{
- Node *lp, *rp;
-
- if (!np)
- return;
-
- if (np->addable >= ADDABLE)
- return;
-
- lp = np->left;
- rp = np->right;
- if (!lp) {
- cgen(rp);
- } else if (!rp) {
- cgen(lp);
- } else {
- Node *p, *q;
- if (lp->complex > rp->complex)
- p = lp, q = rp;
- else
- p = rp, q = lp;
- cgen(p);
- cgen(q);
- }
- (*opnodes[np->op])(np);
-}
-
-void
-generate(void)
-{
- uint8_t size = curfun->u.f.locals;
- static short id = 1000;
- Node **stmt, *np;
-
- retlabel.id = id++;
-
- code(PUSH, NULL, ®s[IX]);
- code(MOV, ®s[IX], ®s[SP]);
- if (size > 6) {
- code(MOV, ®s[HL], imm(-size));
- code(ADD, ®s[HL], ®s[SP]);
- code(MOV, ®s[SP], ®s[HL]);
- } else {
- for (; size != 0; size-= 2)
- code(PUSH, NULL, ®s[HL]);
- }
-
- for (stmt = curfun->u.f.body; np = *stmt; ++stmt)
- cgen(np);
-
- code(MOV, ®s[SP], ®s[IX]);
- retlabel.u.pc = pc;
- pc->label = &retlabel;
- code(POP, ®s[IX], NULL);
- code(RET, NULL, NULL);
-}
-
-/*
- * This is strongly influenced by
- * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps)
- * calculate addresability as follows
- * AUTO => 11 value+fp
- * REGISTER => 13 register
- * STATIC => 12 (value)
- * CONST => 20 $value
- */
-Node *
-genaddable(Node *np)
-{
- Node *lp, *rp;
-
- if (!np)
- return np;
-
- np->complex = 0;
- np->addable = 0;
- lp = np->left;
- rp = np->right;
- switch (np->op) {
- case AUTO:
- np->addable = 11;
- break;
- case REG:
- np->addable = 13;
- break;
- case MEM:
- np->addable = 12;
- break;
- case CONST:
- np->addable = 20;
- break;
- default:
- if (lp)
- genaddable(lp);
- if (rp)
- genaddable(rp);
- break;
- }
-
- if (np->addable > 10)
- return np;
- if (lp)
- np->complex = lp->complex;
- if (rp) {
- int8_t d = np->complex - rp->complex;
-
- if (d == 0)
- ++np->complex;
- else if (d < 0)
- np->complex = rp->complex;
- }
- if (np->complex == 0)
- ++np->complex;
- return np;
-}
-
-void
-addable(void)
-{
- apply(genaddable);
-}
--- a/cc2.old/code.c
+++ /dev/null
@@ -1,229 +1,0 @@
-
-#include <stdarg.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,
- [LDI] = inst2,
- [MOV] = inst2,
- [ADD] = inst2,
- [PUSH] = inst1,
- [POP] = inst1,
- [RET] = inst0,
- [NOP] = inst0,
- [INC] = inst1,
- [SUB] = inst2,
- [DEC] = inst1,
- [JP] = inst1,
- [AND] = inst2,
- [OR] = inst2,
- [XOR] = inst2,
- [CPL] = inst1,
- [NEG] = inst1
-
-};
-
-static char *insttext[] = {
- [LDW] = "LD",
- [LDL] = "LD",
- [LDH] = "LD",
- [LDI] = "LD",
- [MOV] = "LD",
- [ADD] = "ADD",
- [PUSH] = "PUSH",
- [POP] = "POP",
- [RET] = "RET",
- [NOP] = "NOP",
- [INC] = "INC",
- [SUB] = "SUB",
- [DEC] = "DEC",
- [JP] = "JP",
- [AND] = "AND",
- [OR] = "OR",
- [XOR] = "XOR",
- [CPL] = "CPL",
- [NEG] = "NEG"
-};
-
-Inst *pc, *prog;
-
-static void
-nextpc(void)
-{
- Inst *new;
-
- new = xmalloc(sizeof(*new));
-
- if (!pc) {
- new->next = NULL;
- prog = new;
- } else {
- new->next = pc->next;
- pc->next = new;
- }
-
- new->prev = pc;
- new->to.kind = NONE;
- new->from.kind = NONE;
- pc = new;
-}
-
-void
-addr(char op, Node *np, Addr *addr)
-{
- switch (addr->kind = np->op) {
- case REG:
- addr->u.reg = np->reg;
- break;
- case CONST:
- addr->u.i = np->sym->u.imm;
- break;
- case AUTO:
- addr->u.i = np->sym->u.v.off;
- break;
- case LABEL:
- case MEM:
- addr->u.sym = np->sym;
- break;
- case INDEX:
- break;
- default:
- abort();
- }
-}
-
-void
-code(uint8_t op, Node *to, Node *from)
-{
-
- nextpc();
- if (from)
- addr(op, from, &pc->from);
- if (to)
- addr(op, to, &pc->to);
- pc->op = op;
-}
-
-void
-inscode(uint8_t op, Addr *to, Addr *from)
-{
- nextpc();
- if (from)
- pc->from = *from;
- if (to)
- pc->to = *to;
- pc->op = op;
-}
-
-void
-delcode(void)
-{
- Inst *prev = pc->prev, *next = pc->next;
-
- free(pc);
- if (!prev) {
- pc = next;
- prog = NULL;
- } else {
- pc = prev;
- prev->next = next;
- if (next)
- next->prev = prev;
- }
-}
-
-void
-writeout(void)
-{
- if (!prog)
- return;
-
- for (pc = prog; pc; pc = pc->next) {
- if (pc->label)
- printf("L%d:", pc->label->id);
- (*instcode[pc->op])();
- }
-}
-
-static void
-addr2txt(uint8_t op, Addr *a)
-{
- Symbol *sym;
-
- switch (a->kind) {
- case REG:
- fputs(regnames[a->u.reg], stdout);
- break;
- case CONST:
- printf("%d", a->u.i);
- break;
- case PAR:
- case AUTO:
- printf("(IX%+d)", a->u.i);
- break;
- case LABEL:
- sym = a->u.sym;
- printf("L%d", sym->id);
- break;
- case INDEX:
- fputs("(HL)", stdout);
- break;
- case MEM:
- sym = a->u.sym;
- if (sym->name)
- printf((op == LDI) ? "%s" : "(%s)", sym->name);
- else
- printf((op == LDI) ? "T%u" : "(T%u)", sym->id);
- break;
- default:
- abort();
- }
-}
-
-static void
-inst0(void)
-{
- printf("\t%s\n", insttext[pc->op]);
-}
-
-static void
-inst1(void)
-{
- uint8_t op = pc->op;
-
- printf("\t%s\t", insttext[op]);
- addr2txt(op, (pc->to.kind != NONE) ? &pc->to : &pc->from);
- putchar('\n');
-}
-
-static void
-inst2(void)
-{
- uint8_t op = pc->op;
-
- printf("\t%s\t", insttext[op]);
- addr2txt(op, &pc->to);
- putchar(',');
- addr2txt(op, &pc->from);
- putchar('\n');
-}
--- a/cc2.old/generror
+++ /dev/null
@@ -1,19 +1,0 @@
-
-BEGIN {
- print "char *errlist[] = {"
-}
-/^enum nerrors \{/ {
- inhome = 1
-}
-inhome && /E[A-Z]*, / {
- sub(/,/, "", $1)
- printf("\t[%s] = \"", $1)
- for (i = 3; i < NF-1; ++i)
- printf("%s ", $i)
- printf("%s\",\n", $(NF-1));
-}
-inhome && /^}/ {
- print "};"
- inhome = 0
-}
-
--- a/cc2.old/main.c
+++ /dev/null
@@ -1,56 +1,0 @@
-
-#include <stdarg.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "../inc/cc.h"
-
-#include "cc2.h"
-#include "error.h"
-
-char odebug;
-
-void
-error(unsigned nerror, ...)
-{
- va_list va;
- va_start(va, nerror);
- if (nerror >= ENUMERR)
- fprintf(stderr, "incorrect error number '%d'", nerror);
- else
- vfprintf(stderr, errlist[nerror], va);
- va_end(va);
- putc('\n', stderr);
- exit(1);
-}
-
-bool
-moreinput(void)
-{
- int c;
-
-repeat:
- if (feof(stdin))
- return 0;
- if ((c = getchar()) == '\n' || c == EOF)
- goto repeat;
- ungetc(c, stdin);
- return 1;
-}
-
-int
-main(void)
-{
- fputs("cc2 is not updated with the output of cc1", stderr);
- exit(1);
- while (moreinput()) {
- parse();
- optimize();
- addable();
- generate();
- peephole();
- writeout();
- }
- return 0;
-}
--- a/cc2.old/optm.c
+++ /dev/null
@@ -1,51 +1,0 @@
-
-#include <stddef.h>
-#include <inttypes.h>
-
-#include "../inc/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.flags&INTF && np->type.size >= tp->size) {
- np = np->left;
- goto repeat;
- }
- break;
- case OASSIG:
- tp = &np->type;
- break;
- default:
- if (np->type.size > tp->size)
- np->type = *tp;
- break;
- }
-
- np->left = optcasts(np->left, tp);
- np->right = optcasts(np->right, tp);
- return np;
-}
-
-static Node *
-opt(Node *np)
-{
- np = optcasts(np, &np->type);
- return np;
-}
-
-void
-optimize(void)
-{
- apply(opt);
-}
--- a/cc2.old/parser.c
+++ /dev/null
@@ -1,603 +1,0 @@
-
-#include <errno.h>
-#include <inttypes.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "../inc/cc.h"
-#include "../inc/sizes.h"
-
-#include "cc2.h"
-
-#define MAXLINE 200
-#define NR_STACKSIZ 32
-#define NR_NODEPOOL 128
-#define NR_EXPRESSIONS 64
-
-enum {
- LOCAL, GLOBAL, PARAMETER
-};
-
-Symbol *curfun;
-static Node *stack[NR_STACKSIZ], **stackp;
-static Node *listexp[NR_EXPRESSIONS], **listp;
-static Node nodepool[NR_NODEPOOL], *newp;
-
-
-static Type Funct = {
- .letter = L_FUNCTION,
-};
-
-static Type l_int8 = {
- .letter = L_INT8,
- .size = 1,
- .align = 2,
- .flags = SIGNF | INTF
-};
-
-static Type l_int16 = {
- .letter = L_INT16,
- .size = 2,
- .align = 2,
- .flags = SIGNF | INTF
-
-};
-
-static Type l_int32 = {
- .letter = L_INT32,
- .size = 4,
- .align = 4,
- .flags = SIGNF | INTF
-
-};
-
-static Type l_int64 = {
- .letter = L_INT64,
- .size = 8,
- .align = 8,
- .flags = SIGNF | INTF
-
-};
-
-static Type l_uint8 = {
- .letter = L_UINT8,
- .size = 1,
- .align = 2,
- .flags = INTF
-};
-
-static Type l_uint16 = {
- .letter = L_UINT16,
- .size = 2,
- .align = 2,
- .flags = INTF
-};
-
-static Type l_uint32 = {
- .letter = L_UINT32,
- .size = 4,
- .align = 4,
- .flags = INTF
-};
-
-static Type l_uint64 = {
- .letter = L_UINT64,
- .size = 8,
- .align = 8,
- .flags = INTF
-};
-
-static void cast(char *), operator(char *), assignment(char *), increment(char *),
- globvar(char *), localvar(char *), paramvar(char *), label(char *),
- immediate(char *), unary(char *), oreturn(char *);
-
-/*TODO: Remove hardcoded symbols */
-
-static void (*optbl[])(char *) = {
- [L_INT8] = cast,
- [L_INT16] = cast,
- [L_INT32] = cast,
- [L_INT64] = cast,
- [L_UINT8] = cast,
- [L_UINT16] = cast,
- [L_UINT32] = cast,
- [L_UINT64] = cast,
- [L_BOOL] = cast,
- [L_FLOAT] = cast,
- [L_DOUBLE] = cast,
- [L_LDOUBLE] = cast,
- [L_POINTER] = cast,
- [L_VOID] = cast,
- ['+'] = operator,
- ['%'] = operator,
- ['-'] = operator,
- ['*'] = operator,
- ['/'] = operator,
- ['l'] = operator,
- ['r'] = operator,
- ['&'] = operator,
- ['|'] = operator,
- ['^'] = operator,
- [':'] = assignment,
- [';'] = increment,
- ['Y'] = globvar,
- ['A'] = localvar,
- ['K'] = localvar,
- ['T'] = localvar,
- ['G'] = globvar,
- ['P'] = paramvar,
- ['L'] = label,
- ['#'] = immediate,
- ['@'] = unary,
- ['a'] = unary,
- ['<'] = operator,
- ['>'] = operator,
- [']'] = operator,
- ['['] = operator,
- ['='] = operator,
- ['!'] = unary,
- ['y'] = oreturn,
- ['j'] = NULL,
- ['o'] = operator,
- ['_'] = unary,
- ['~'] = unary,
- [','] = operator,
- ['\177'] = NULL
-};
-
-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 *(*fun)(Node *))
-{
- Node **list, *np;
-
- for (list = curfun->u.f.body; np = *list; ++list)
- *list++ = (*fun)(np);
-}
-
-static Symbol *
-parameter(char *num)
-{
- static Symbol tbl[NR_FUNPARAM];
- Symbol *sym;
- unsigned i = atoi(num);
-
- if (!curfun)
- error(ESYNTAX);
- if (i >= NR_FUNPARAM)
- error(EPARNUM);
- sym = &tbl[i];
- sym->id = i;
- return sym;
-}
-
-static Symbol *
-local(char *num)
-{
- static Symbol tbl[NR_INT_IDENT];
- Symbol *sym;
- unsigned i = atoi(num);
-
- if (!curfun)
- error(ESYNTAX);
- if (i >= NR_INT_IDENT)
- error(EINTNUM);
- sym = &tbl[i];
- sym->id = i;
- return sym;
-}
-
-static Symbol *
-global(char *num)
-{
- static Symbol tbl[NR_EXT_IDENT];
- Symbol *sym;
- unsigned i = atoi(num);
-
- if (i >= NR_EXT_IDENT)
- error(EEXTNUM);
-
- sym = &tbl[i];
- sym->id = i;
- return sym;
-}
-
-static Node *
-newnode(void)
-{
- if (newp == &nodepool[NR_NODEPOOL])
- error(ENODEOV);
- return newp++;
-}
-
-Node *
-imm(TINT i)
-{
- Node *np = newnode();
-
- np->op = CONST;
- np->type = l_int16;
- /* FIX: memory leak */
- np->sym = xmalloc(sizeof(Symbol));
- np->sym->u.imm = i;
- np->left = np->right = NULL;
- return np;
-}
-
-static void
-push(Node *np)
-{
- if (stackp == &stack[NR_STACKSIZ])
- error(ESTACKO);
- *stackp++ = np;
-}
-
-static Node *
-pop(void)
-{
- if (stackp == stack)
- error(ESTACKU);
- return *--stackp;
-}
-
-static Type *
-gettype(char *type)
-{
- switch (type[0]) {
- case L_INT8:
- return &l_int8;
- case L_INT16:
- return &l_int16;
- case L_INT32:
- return &l_int32;
- case L_INT64:
- return &l_int64;
- case L_UINT8:
- return &l_uint8;
- case L_UINT16:
- return &l_uint16;
- case L_UINT32:
- return &l_uint32;
- case L_UINT64:
- return &l_uint64;
- case L_FUNCTION:
- return &Funct;
- default:
- error(ETYPERR);
- }
-}
-
-static Symbol *
-symbol(uint8_t t, char *token)
-{
- Symbol *sym;
- static Symbol *(*tbl[3])(char *)= {
- [LOCAL] = local,
- [GLOBAL] = global,
- [PARAMETER] = parameter
- };
- sym = (*tbl[t])(token+1);
- sym->kind = *token;
- return sym;
-}
-
-static void
-variable(uint8_t t, char *token)
-{
- Node *np = newnode();
- Symbol *sym = symbol(t, token);
-
- np->sym = sym;
- np->op = sym->u.v.sclass;
- np->type = sym->u.v.type;
- np->left = np->right = NULL;
- push(np);
-}
-
-static void
-localvar(char *token)
-{
- variable(LOCAL, token);
-}
-
-static void
-globvar(char *token)
-{
- variable(GLOBAL, token);
-}
-
-static void
-paramvar(char *token)
-{
- variable(PARAMETER, token);
-}
-
-static void
-immediate(char *token)
-{
- /* TODO: check type of immediate */
- push(imm(atoi(token+2)));
-}
-
-static void
-unary(char *token)
-{
- Node *np = newnode();
-
- np->right = NULL;
- np->left = pop();
- np->type = *gettype(token+1);
- np->op = token[0];
- push(np);
-}
-
-static void
-operator(char *token)
-{
- Node *np = newnode();
-
- np->right = pop();
- np->left = pop();
- np->type = *gettype(token+1);
- np->op = token[0];
- push(np);
-}
-
-static void
-label(char *token)
-{
- Node *np = newnode();
-
- np->left = np->right = NULL;
- np->op = LABEL;
- np->sym = local(token);
- push(np);
-}
-
-static void
-increment(char *token)
-{
- Node *np = newnode();
-
- np->right = pop();
- np->left = pop();
- np->type = *gettype(token+2);
- np->op = token[0];
- switch (np->subop = token[1]) {
- case '-': case '+':
- push(np);
- break;
- default:
- error(ESYNTAX);
- }
-}
-
-static void
-assignment(char *token)
-{
- Node *np = newnode();
-
- np->right = pop();
- np->left = pop();
- np->op = *token;
- switch (*++token) {
- case OADD: case OSUB: case OINC: case OMOD: case ODIV:
- case OSHL: case OSHR: case OBAND: case OBOR: case OBXOR:
- np->subop = *++token;
- default:
- np->type = *gettype(token);
- break;
- }
- push(np);
-}
-
-static void
-cast(char *token)
-{
- Node *np = newnode();
-
- np->right = NULL;
- np->left = pop();
- np->op = OCAST;
- np->type = *gettype(token+1);
- push(np);
-}
-
-static void
-expr(char *token)
-{
- void (*fun)(char *);
- unsigned c;
-
- do {
- if ((c = token[0]) > 0x7f || (fun = optbl[c]) == NULL)
- error(ESYNTAX);
- (*fun)(token);
- } while (token = strtok(NULL, "\t"));
-}
-
-static void
-expression(char *token)
-{
- Node *np;
-
- if (!curfun)
- error(ESYNTAX);
-
- expr(token);
-
- np = pop();
- if (stackp != stack)
- error(EEXPBAL);
- if (listp == &listexp[NR_EXPRESSIONS])
- error(EEXPROV);
- *listp++ = np;
-}
-
-static void
-oreturn(char *token)
-{
- Node *np = newnode(), *lp;
-
- np->op = token[0];
-
- if (token = strtok(NULL, "\t")) {
- expr(token);
- lp = pop();
- np->left = lp;
- np->type = lp->type;
- } else {
- np->left = NULL;
- }
- np->right = NULL;
- push(np);
-}
-
-static void
-deflabel(char *token)
-{
- Symbol *sym;
-
- if (!curfun)
- error(ESYNTAX);
- sym = local(token);
-}
-
-static Symbol *
-declaration(uint8_t t, char class, char *token)
-{
- Symbol *sym = symbol(t, token);
- char *s;
-
- free(sym->name);
- memset(sym, 0, sizeof(*sym));
- sym->u.v.sclass = class;
-
- if ((s = strtok(NULL, "\t")) == NULL)
- error(ESYNTAX);
- sym->u.v.type = *gettype(s);
- if ((s = strtok(NULL, "\t")) != NULL)
- sym->name = xstrdup(s);
-
- return sym;
-}
-
-static void
-globdcl(char *token)
-{
- Symbol *sym = declaration(GLOBAL, MEM, token);
-
- switch (token[0]) {
- case 'X':
- sym->extrn = 1;
- break;
- case 'G':
- sym->public = 1;
- break;
- }
-
- if (sym->u.v.type.letter != L_FUNCTION)
- return;
-
- if (curfun)
- error(ESYNTAX);
-
- curfun = sym;
- sym->u.f.body = listp = listexp;
- newp = nodepool;
-}
-
-static void
-paramdcl(char *token)
-{
- Symbol *sym = declaration(PARAMETER, AUTO, token);
- sym->u.v.off = -curfun->u.f.params;
- curfun->u.f.params += sym->u.v.type.size;
-}
-
-static void
-localdcl(char *token)
-{
- Symbol *sym = declaration(LOCAL, token[0], token);
- char sclass = *token;
-
- if (sclass == 'A' || sclass == 'R') {
- uint8_t size = sym->u.v.type.size;
- /* stack elements are 2 byte multiple */
- if (size == 1)
- ++size;
- curfun->u.f.locals += size;
- sym->u.v.off = curfun->u.f.locals;
- }
-}
-
-void
-parse(void)
-{
- void (*fun)(char *tok);
- uint8_t len;
- int c;
- char line[MAXLINE];
-
- curfun = NULL;
- stackp = stack;
- listp = listexp;
- newp = nodepool;
-
- for (;;) {
- switch (c = getchar()) {
- case 'L':
- fun = deflabel;
- break;
- case '\t':
- fun = expression;
- break;
- case 'S':
- /* TODO: struct */
- break;
- case 'P':
- fun = paramdcl;
- break;
- case 'A': case 'R': case 'T':
- fun = localdcl;
- break;
- case 'Y': case 'G':
- fun = globdcl;
- break;
- case '}':
- if (curfun)
- return;
- default:
- goto syntax_error;
- }
-
- ungetc(c, stdin);
- if (!fgets(line, sizeof(line), stdin))
- break;
- len = strlen(line);
- if (line[len-1] != '\n')
- error(ELNLINE);
- line[len-1] = '\0';
- (*fun)(strtok(line, "\t"));
- }
-
-syntax_error:
- error(ESYNTAX);
-}
--- a/cc2.old/peep.c
+++ /dev/null
@@ -1,39 +1,0 @@
-
-#include <inttypes.h>
-#include <stddef.h>
-
-#include "../inc/cc.h"
-#include "cc2.h"
-
-void
-peephole(void)
-{
- Addr to, from;
- TINT i;
- uint8_t op;
-
- for (pc = prog; pc; pc = pc->next) {
- to = pc->to;
- from = pc->from;
-
- switch (pc->op) {
- case SUB:
- case ADD:
- if (from.kind == CONST) {
- if ((i = from.u.i) == 0 || i < 4) {
- delcode();
- op = (pc->op == ADD) ? INC : DEC;
-
- while (i--)
- inscode(op, &to, NULL);
- }
- /* TODO: More optimizations (ex: -1) */
- }
- break;
- case JP:
- if (to.u.sym->u.pc == pc->next)
- delcode();
- break;
- }
- }
-}
--- a/cc2/cc2.h
+++ b/cc2/cc2.h
@@ -81,7 +81,7 @@
OBXOR = '^',
OCPL = '~',
OASSIG = ':',
- ONEG = '_',
+ OSNEG = '_',
OCALL = 'c',
OPAR = 'p',
OFIELD = '.',
@@ -91,12 +91,13 @@
OADDR = '\'',
OAND = 'a',
OOR = 'o',
+ ONEG = 'n',
OPTR = '@',
OCAST = 'g',
OINC = 'i',
ODEC = 'd',
/*statements */
- ONOP = 'n',
+ ONOP = 'q',
OJMP = 'j',
OBRANCH = 'y',
ORET = 'h',
--- a/cc2/parser.c
+++ b/cc2/parser.c
@@ -92,11 +92,12 @@
['\t'] = { stmt, NULL, 0},
['~'] = { NULL, unary, .u.op = OCPL},
- ['_'] = { NULL, unary, .u.op = ONEG},
+ ['_'] = { NULL, unary, .u.op = OSNEG},
['\''] = { NULL, unary, .u.op = OADDR},
['@'] = { NULL, unary, .u.op = OPTR},
['g'] = { NULL, unary, .u.op = OCAST},
['p'] = { NULL, unary, .u.op = OPAR},
+ ['n'] = { NULL, unary, .u.op = ONEG},
['a'] = { NULL, binary, .u.op = OAND},
['o'] = { NULL, binary, .u.op = OOR},
--- a/libc/include/amd64-sysv/assert.h
+++ b/libc/include/amd64-sysv/assert.h
@@ -3,7 +3,7 @@
#define _ASSERT_H
#ifndef NDEBUG
-#define assert(exp) __assert(#exp, __FILE__, __LINE__)
+#define assert(exp) __assert(exp, #exp, __FILE__, __LINE__)
#endif
#endif
--- a/libc/include/amd64-sysv/stdio.h
+++ b/libc/include/amd64-sysv/stdio.h
@@ -75,5 +75,5 @@
extern FILE *tmpfile(void);
extern FILE *tmpnam(char *s);
-extern FILE *stdin, *stdio, *stderr;
+extern FILE *stdin, *stdout, *stderr;
#endif
--- a/libc/include/i386-sysv/assert.h
+++ b/libc/include/i386-sysv/assert.h
@@ -3,7 +3,7 @@
#define _ASSERT_H
#ifndef NDEBUG
-#define assert(exp) __assert(#exp, __FILE__, __LINE__)
+#define assert(exp) __assert(exp, #exp, __FILE__, __LINE__)
#endif
#endif
--- a/libc/include/i386-sysv/stdio.h
+++ b/libc/include/i386-sysv/stdio.h
@@ -75,5 +75,5 @@
extern FILE *tmpfile(void);
extern FILE *tmpnam(char *s);
-extern FILE *stdin, *stdio, *stderr;
+extern FILE *stdin, *stdout, *stderr;
#endif
--- a/libc/include/qbe/assert.h
+++ b/libc/include/qbe/assert.h
@@ -3,7 +3,7 @@
#define _ASSERT_H
#ifndef NDEBUG
-#define assert(exp) __assert(#exp, __FILE__, __LINE__)
+#define assert(exp) __assert(exp, #exp, __FILE__, __LINE__)
#endif
#endif
--- a/libc/include/qbe/stdio.h
+++ b/libc/include/qbe/stdio.h
@@ -75,5 +75,5 @@
extern FILE *tmpfile(void);
extern FILE *tmpnam(char *s);
-extern FILE *stdin, *stdio, *stderr;
+extern FILE *stdin, *stdout, *stderr;
#endif
--- a/libc/include/z80/assert.h
+++ b/libc/include/z80/assert.h
@@ -3,7 +3,7 @@
#define _ASSERT_H
#ifndef NDEBUG
-#define assert(exp) __assert(#exp, __FILE__, __LINE__)
+#define assert(exp) __assert(exp, #exp, __FILE__, __LINE__)
#endif
#endif
--- a/libc/include/z80/stdio.h
+++ b/libc/include/z80/stdio.h
@@ -75,5 +75,5 @@
extern FILE *tmpfile(void);
extern FILE *tmpnam(char *s);
-extern FILE *stdin, *stdio, *stderr;
+extern FILE *stdin, *stdout, *stderr;
#endif