scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | README | LICENSE

commit 912db5e91a1141ac0d91c484ffe4472fad91bad7
parent 72e5cb42ece0bd4ad683ee463496d8cbf5458df9
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Fri, 12 Aug 2016 09:06:43 +0200

Merge branch 'master' into qbe

Diffstat:
MREADME | 8++++++++
Mcc1/cc1.h | 5+++--
Mcc1/code.c | 4+++-
Mcc1/cpp.c | 22++++++++++++----------
Mcc1/decl.c | 14++++++++------
Mcc1/expr.c | 271+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
Mcc1/fold.c | 6++++--
Mcc1/init.c | 2+-
Mcc1/main.c | 2+-
Mcc1/tests/test001.c | 6+++---
Acc1/tests/test065.c | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcc1/types.c | 10++++++----
Dcc2.old/Makefile | 23-----------------------
Dcc2.old/cast.patch | 61-------------------------------------------------------------
Dcc2.old/cc2.h | 179-------------------------------------------------------------------------------
Dcc2.old/cgen.c | 602-------------------------------------------------------------------------------
Dcc2.old/code.c | 229-------------------------------------------------------------------------------
Dcc2.old/generror | 19-------------------
Dcc2.old/main.c | 56--------------------------------------------------------
Dcc2.old/optm.c | 51---------------------------------------------------
Dcc2.old/parser.c | 603-------------------------------------------------------------------------------
Dcc2.old/peep.c | 39---------------------------------------
Mcc2/cc2.h | 5+++--
Mcc2/parser.c | 3++-
Mlibc/include/amd64-sysv/assert.h | 2+-
Mlibc/include/amd64-sysv/stdio.h | 2+-
Mlibc/include/i386-sysv/assert.h | 2+-
Mlibc/include/i386-sysv/stdio.h | 2+-
Mlibc/include/qbe/assert.h | 2+-
Mlibc/include/qbe/stdio.h | 2+-
Mlibc/include/z80/assert.h | 2+-
Mlibc/include/z80/stdio.h | 2+-
32 files changed, 284 insertions(+), 2018 deletions(-)

diff --git a/README b/README @@ -63,3 +63,11 @@ This complexity is not needed at all as function pointers fix all these 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. diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -200,6 +200,7 @@ enum op { OBAND, OBXOR, OBOR, + OSNEG, ONEG, OCPL, OAND, @@ -349,7 +350,7 @@ extern void errorp(char *fmt, ...); 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 cpp(void); 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); /* diff --git a/cc1/code.c b/cc1/code.c @@ -50,7 +50,8 @@ char *optxt[] = { [OA_XOR] = ":^", [OA_OR] = ":|", [OADDR] = "'", - [ONEG] = "_", + [OSNEG] = "_", + [ONEG] = "n", [OCPL] = "~", [OAND] = "a", [OOR] = "o", @@ -104,6 +105,7 @@ void (*opcode[])(unsigned, void *) = { [OA_XOR] = emitbin, [OA_OR] = emitbin, [OADDR] = emitbin, + [OSNEG] = emitbin, [ONEG] = emitbin, [OCPL] = emitbin, [OAND] = emitbin, diff --git a/cc1/cpp.c b/cc1/cpp.c @@ -23,7 +23,7 @@ unsigned cppctx; 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 @@ defdefine(char *macro, char *val) 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 @@ icpp(void) 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 @@ elseclause(void) { 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; diff --git a/cc1/decl.c b/cc1/decl.c @@ -118,13 +118,15 @@ arydcl(struct declarators *dp) } 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 @@ parameter(struct decl *dcl) 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 @@ field(struct decl *dcl) 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 @@ redcl(Symbol *sym, Type *tp, Symbol **pars, int sclass) 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 @@ identifier(struct decl *dcl) 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 */ diff --git a/cc1/expr.c b/cc1/expr.c @@ -37,22 +37,6 @@ cmpnode(Node *np, TUINT val) 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 @@ null(Node *np) static Node * chkternary(Node *yes, Node *no) { - yes = decay(yes); - no = decay(no); - /* * FIXME: * We are ignoring type qualifiers here, @@ -154,7 +135,7 @@ chkternary(Node *yes, Node *no) * 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 @@ chkternary(Node *yes, Node *no) 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 @@ numericaluop(char op, Node *np) 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 @@ convert(Node *np, Type *newtp, char iscast) { Type *oldtp = np->type; - if (eqtype(newtp, oldtp)) + if (eqtype(newtp, oldtp, 0)) return np; switch (oldtp->op) { @@ -295,7 +276,8 @@ convert(Node *np, Type *newtp, char iscast) 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 @@ parithmetic(char op, Node *lp, Node *rp) 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 @@ parithmetic(char op, Node *lp, Node *rp) 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 @@ pcompare(char op, Node *lp, Node *rp) 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 @@ compare(char op, Node *lp, Node *rp) { Type *ltp, *rtp; - lp = decay(lp); - rp = decay(rp); - ltp = lp->type; rtp = rp->type; @@ -409,8 +397,6 @@ int 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 @@ negop(int op) 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 @@ negate(Node *np) 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 @@ free_np: 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 @@ content(char op, Node *np) 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 @@ array(Node *lp, Node *rp) 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 @@ array(Node *lp, Node *rp) 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 @@ incdec(Node *np, char op) 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,15 +581,25 @@ address(char op, Node *np) { 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); @@ -585,7 +611,6 @@ address(char op, Node *np) 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 @@ primary(void) sym->flags |= SHASINIT; emit(ODECL, sym); emit(OINIT, np); - np = decay(varnode(sym)); + np = varnode(sym); next(); break; case CONSTANT: @@ -688,7 +713,7 @@ arguments(Node *np) toomany = 0; do { - arg = decay(assign()); + arg = assign(); argtype = *targs; if (argtype == ellipsistype) { n = 0; @@ -727,42 +752,7 @@ no_pars: return node(OCALL, rettype, np, par); } -static Node * -postfix(Node *lp) -{ - Node *rp; - - 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 Node *unary(int); static Type * typeof(Node *np) @@ -788,26 +778,75 @@ sizeexp(void) tp = typename(); break; default: - tp = typeof(unary()); + tp = typeof(unary(0)); break; } expect(')'); 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,29 +854,31 @@ unary(void) 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; static int nested; if (!accept('(')) - return unary(); + return unary(needdecay); switch (yytoken) { case TQUALIFIER: @@ -852,7 +893,7 @@ cast(void) 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 @@ mul(void) 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 @@ mul(void) default: return np; } next(); - np = (*fun)(op, np, cast()); + np = (*fun)(op, np, cast(1)); } } diff --git a/cc1/fold.c b/cc1/fold.c @@ -188,7 +188,8 @@ foldint(int op, Symbol *res, TINT l, TINT r) 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 @@ folduint(int op, Symbol *res, TUINT l, TUINT r) 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; diff --git a/cc1/init.c b/cc1/init.c @@ -134,7 +134,7 @@ initialize(Type *tp) 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; diff --git a/cc1/main.c b/cc1/main.c @@ -38,7 +38,7 @@ defmacro(char *macro) else p = "1"; - defdefine(macro, p); + defdefine(macro, p, "command-line"); } static void diff --git a/cc1/tests/test001.c b/cc1/tests/test001.c @@ -9,13 +9,13 @@ X4 I F "printf 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 } */ diff --git a/cc1/tests/test065.c b/cc1/tests/test065.c @@ -0,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]; +} diff --git a/cc1/types.c b/cc1/types.c @@ -296,7 +296,7 @@ mktype(Type *tp, int op, TINT nelem, Type *pars[]) 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 @@ mktype(Type *tp, int op, TINT nelem, Type *pars[]) } int -eqtype(Type *tp1, Type *tp2) +eqtype(Type *tp1, Type *tp2, int equiv) { TINT n; Type **p1, **p2; @@ -333,16 +333,18 @@ eqtype(Type *tp1, Type *tp2) 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; diff --git a/cc2.old/Makefile b/cc2.old/Makefile @@ -1,23 +0,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 - diff --git a/cc2.old/cast.patch b/cc2.old/cast.patch @@ -1,61 +0,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 *) = { diff --git a/cc2.old/cc2.h b/cc2.old/cc2.h @@ -1,179 +0,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); diff --git a/cc2.old/cgen.c b/cc2.old/cgen.c @@ -1,602 +0,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 = &regs[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 = &regs[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, &regs[lower[reg]], np); - code(LDH, &regs[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, &regs[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, &regs[IX]); - code(MOV, &regs[IX], &regs[SP]); - if (size > 6) { - code(MOV, &regs[HL], imm(-size)); - code(ADD, &regs[HL], &regs[SP]); - code(MOV, &regs[SP], &regs[HL]); - } else { - for (; size != 0; size-= 2) - code(PUSH, NULL, &regs[HL]); - } - - for (stmt = curfun->u.f.body; np = *stmt; ++stmt) - cgen(np); - - code(MOV, &regs[SP], &regs[IX]); - retlabel.u.pc = pc; - pc->label = &retlabel; - code(POP, &regs[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); -} diff --git a/cc2.old/code.c b/cc2.old/code.c @@ -1,229 +0,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'); -} diff --git a/cc2.old/generror b/cc2.old/generror @@ -1,19 +0,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 -} - diff --git a/cc2.old/main.c b/cc2.old/main.c @@ -1,56 +0,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; -} diff --git a/cc2.old/optm.c b/cc2.old/optm.c @@ -1,51 +0,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); -} diff --git a/cc2.old/parser.c b/cc2.old/parser.c @@ -1,603 +0,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); -} diff --git a/cc2.old/peep.c b/cc2.old/peep.c @@ -1,39 +0,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; - } - } -} diff --git a/cc2/cc2.h b/cc2/cc2.h @@ -81,7 +81,7 @@ enum op { OBXOR = '^', OCPL = '~', OASSIG = ':', - ONEG = '_', + OSNEG = '_', OCALL = 'c', OPAR = 'p', OFIELD = '.', @@ -91,12 +91,13 @@ enum op { 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', diff --git a/cc2/parser.c b/cc2/parser.c @@ -92,11 +92,12 @@ static struct decoc { ['\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}, diff --git 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 diff --git a/libc/include/amd64-sysv/stdio.h b/libc/include/amd64-sysv/stdio.h @@ -75,5 +75,5 @@ extern int rename(const char *old, const char *new); extern FILE *tmpfile(void); extern FILE *tmpnam(char *s); -extern FILE *stdin, *stdio, *stderr; +extern FILE *stdin, *stdout, *stderr; #endif diff --git 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 diff --git a/libc/include/i386-sysv/stdio.h b/libc/include/i386-sysv/stdio.h @@ -75,5 +75,5 @@ extern int rename(const char *old, const char *new); extern FILE *tmpfile(void); extern FILE *tmpnam(char *s); -extern FILE *stdin, *stdio, *stderr; +extern FILE *stdin, *stdout, *stderr; #endif diff --git 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 diff --git a/libc/include/qbe/stdio.h b/libc/include/qbe/stdio.h @@ -75,5 +75,5 @@ extern int rename(const char *old, const char *new); extern FILE *tmpfile(void); extern FILE *tmpnam(char *s); -extern FILE *stdin, *stdio, *stderr; +extern FILE *stdin, *stdout, *stderr; #endif diff --git 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 diff --git a/libc/include/z80/stdio.h b/libc/include/z80/stdio.h @@ -75,5 +75,5 @@ extern int rename(const char *old, const char *new); extern FILE *tmpfile(void); extern FILE *tmpnam(char *s); -extern FILE *stdin, *stdio, *stderr; +extern FILE *stdin, *stdout, *stderr; #endif