#include "cc.h" typedef struct Ftab Ftab;struct Ftab{ char op; char* name; char typ;};typedef struct Gtab Gtab;struct Gtab{ char etype; char* name;}; Ftab ftabinit[OEND];Gtab gtabinit[NTYPE]; intisfunct(Node *n){ Type *t, *t1; Funct *f; Node *l; Sym *s; int o; o = n->op; if(n->left == Z) goto no; t = n->left->type; if(t == T) goto no; f = t->funct; switch(o) { case OAS: // put cast on rhs case OASI: case OASADD: case OASAND: case OASASHL: case OASASHR: case OASDIV: case OASLDIV: case OASLMOD: case OASLMUL: case OASLSHR: case OASMOD: case OASMUL: case OASOR: case OASSUB: case OASXOR: if(n->right == Z) goto no; t1 = n->right->type; if(t1 == T) goto no; if(t1->funct == f) break; l = new(OXXX, Z, Z); *l = *n->right; n->right->left = l; n->right->right = Z; n->right->type = t; n->right->op = OCAST; if(!isfunct(n->right)) prtree(n, "isfunc !"); break; case OCAST: // t f(T) or T f(t) t1 = n->type; if(t1 == T) goto no; if(f != nil) { s = f->castfr[t1->etype]; if(s == S) goto no; n->right = n->left; goto build; } f = t1->funct; if(f != nil) { s = f->castto[t->etype]; if(s == S) goto no; n->right = n->left; goto build; } goto no; } if(f == nil) goto no; s = f->sym[o]; if(s == S) goto no; /* * the answer is yes, * now we rewrite the node * and give diagnostics */ switch(o) { default: diag(n, "isfunct op missing %O\n", o); goto bad; case OADD: // T f(T, T) case OAND: case OASHL: case OASHR: case ODIV: case OLDIV: case OLMOD: case OLMUL: case OLSHR: case OMOD: case OMUL: case OOR: case OSUB: case OXOR: case OEQ: // int f(T, T) case OGE: case OGT: case OHI: case OHS: case OLE: case OLO: case OLS: case OLT: case ONE: if(n->right == Z) goto bad; t1 = n->right->type; if(t1 == T) goto bad; if(t1->funct != f) goto bad; n->right = new(OLIST, n->left, n->right); break; case OAS: // structure copies done by the compiler case OASI: goto no; case OASADD: // T f(T*, T) case OASAND: case OASASHL: case OASASHR: case OASDIV: case OASLDIV: case OASLMOD: case OASLMUL: case OASLSHR: case OASMOD: case OASMUL: case OASOR: case OASSUB: case OASXOR: if(n->right == Z) goto bad; t1 = n->right->type; if(t1 == T) goto bad; if(t1->funct != f) goto bad; n->right = new(OLIST, new(OADDR, n->left, Z), n->right); break; case OPOS: // T f(T) case ONEG: case ONOT: case OCOM: n->right = n->left; break; } build: l = new(ONAME, Z, Z); l->sym = s; l->type = s->type; l->etype = s->type->etype; l->xoffset = s->offset; l->class = s->class; tcomo(l, 0); n->op = OFUNC; n->left = l; n->type = l->type->link; if(tcompat(n, T, l->type, tfunct)) goto bad; if(tcoma(n->left, n->right, l->type->down, 1)) goto bad; return 1; no: return 0; bad: diag(n, "cant rewrite typestr for op %O\n", o); prtree(n, "isfunct"); n->type = T; return 1;} voiddclfunct(Type *t, Sym *s){ Funct *f; Node *n; Type *f1, *f2, *f3, *f4; int o, i, c; char str[100]; if(t->funct) return; // recognize generated tag of dorm _%d_ if(t->tag == S) goto bad; for(i=0; c = t->tag->name[i]; i++) { if(c == '_') { if(i == 0 || t->tag->name[i+1] == 0) continue; break; } if(c < '0' || c > '9') break; } if(c == 0) goto bad; f = alloc(sizeof(*f)); for(o=0; o<sizeof(f->sym); o++) f->sym[o] = S; t->funct = f; f1 = typ(TFUNC, t); f1->down = copytyp(t); f1->down->down = t; f2 = typ(TFUNC, types[TINT]); f2->down = copytyp(t); f2->down->down = t; f3 = typ(TFUNC, t); f3->down = typ(TIND, t); f3->down->down = t; f4 = typ(TFUNC, t); f4->down = t; for(i=0;; i++) { o = ftabinit[i].op; if(o == OXXX) break; sprint(str, "%s_%s_", t->tag->name, ftabinit[i].name); n = new(ONAME, Z, Z); n->sym = slookup(str); f->sym[o] = n->sym; switch(ftabinit[i].typ) { default: diag(Z, "dclfunct op missing %d\n", ftabinit[i].typ); break; case 1: // T f(T,T) + dodecl(xdecl, CEXTERN, f1, n); break; case 2: // int f(T,T) == dodecl(xdecl, CEXTERN, f2, n); break; case 3: // void f(T*,T) += dodecl(xdecl, CEXTERN, f3, n); break; case 4: // T f(T) ~ dodecl(xdecl, CEXTERN, f4, n); break; } } for(i=0;; i++) { o = gtabinit[i].etype; if(o == TXXX) break; /* * OCAST types T1 _T2_T1_(T2) */ sprint(str, "_%s%s_", gtabinit[i].name, t->tag->name); n = new(ONAME, Z, Z); n->sym = slookup(str); f->castto[o] = n->sym; f1 = typ(TFUNC, t); f1->down = types[o]; dodecl(xdecl, CEXTERN, f1, n); sprint(str, "%s_%s_", t->tag->name, gtabinit[i].name); n = new(ONAME, Z, Z); n->sym = slookup(str); f->castfr[o] = n->sym; f1 = typ(TFUNC, types[o]); f1->down = t; dodecl(xdecl, CEXTERN, f1, n); } return;bad: diag(Z, "dclfunct bad %T %s\n", t, s->name);} Gtab gtabinit[NTYPE] ={ TCHAR, "c", TUCHAR, "uc", TSHORT, "h", TUSHORT, "uh", TINT, "i", TUINT, "ui", TLONG, "l", TULONG, "ul", TVLONG, "v", TUVLONG, "uv", TFLOAT, "f", TDOUBLE, "d", TXXX}; Ftab ftabinit[OEND] ={ OADD, "add", 1, OAND, "and", 1, OASHL, "ashl", 1, OASHR, "ashr", 1, ODIV, "div", 1, OLDIV, "ldiv", 1, OLMOD, "lmod", 1, OLMUL, "lmul", 1, OLSHR, "lshr", 1, OMOD, "mod", 1, OMUL, "mul", 1, OOR, "or", 1, OSUB, "sub", 1, OXOR, "xor", 1, OEQ, "eq", 2, OGE, "ge", 2, OGT, "gt", 2, OHI, "hi", 2, OHS, "hs", 2, OLE, "le", 2, OLO, "lo", 2, OLS, "ls", 2, OLT, "lt", 2, ONE, "ne", 2, OASADD, "asadd", 3, OASAND, "asand", 3, OASASHL, "asashl", 3, OASASHR, "asashr", 3, OASDIV, "asdiv", 3, OASLDIV, "asldiv", 3, OASLMOD, "aslmod", 3, OASLMUL, "aslmul", 3, OASLSHR, "aslshr", 3, OASMOD, "asmod", 3, OASMUL, "asmul", 3, OASOR, "asor", 3, OASSUB, "assub", 3, OASXOR, "asxor", 3, OPOS, "pos", 4, ONEG, "neg", 4, OCOM, "com", 4, ONOT, "not", 4, // OPOSTDEC,// OPOSTINC,// OPREDEC,// OPREINC, OXXX,}; // Node* nodtestv; // Node* nodvpp;// Node* nodppv;// Node* nodvmm;// Node* nodmmv;
#include "cc.h"
typedef struct Ftab Ftab;
struct Ftab
{
char op;
char* name;
char typ;
};
typedef struct Gtab Gtab;
struct Gtab
{
char etype;
char* name;
};
Ftab ftabinit[OEND];
Gtab gtabinit[NTYPE];
int
isfunct(Node *n)
{
Type *t, *t1;
Funct *f;
Node *l;
Sym *s;
int o;
o = n->op;
if(n->left == Z)
goto no;
t = n->left->type;
if(t == T)
goto no;
f = t->funct;
switch(o) {
case OAS: // put cast on rhs
case OASI:
case OASADD:
case OASAND:
case OASASHL:
case OASASHR:
case OASDIV:
case OASLDIV:
case OASLMOD:
case OASLMUL:
case OASLSHR:
case OASMOD:
case OASMUL:
case OASOR:
case OASSUB:
case OASXOR:
if(n->right == Z)
goto no;
t1 = n->right->type;
if(t1 == T)
goto no;
if(t1->funct == f)
break;
l = new(OXXX, Z, Z);
*l = *n->right;
n->right->left = l;
n->right->right = Z;
n->right->type = t;
n->right->op = OCAST;
if(!isfunct(n->right))
prtree(n, "isfunc !");
break;
case OCAST: // t f(T) or T f(t)
t1 = n->type;
if(t1 == T)
goto no;
if(f != nil) {
s = f->castfr[t1->etype];
if(s == S)
goto no;
n->right = n->left;
goto build;
}
f = t1->funct;
if(f != nil) {
s = f->castto[t->etype];
if(s == S)
goto no;
n->right = n->left;
goto build;
}
goto no;
}
if(f == nil)
goto no;
s = f->sym[o];
if(s == S)
goto no;
/*
* the answer is yes,
* now we rewrite the node
* and give diagnostics
*/
switch(o) {
default:
diag(n, "isfunct op missing %O\n", o);
goto bad;
case OADD: // T f(T, T)
case OAND:
case OASHL:
case OASHR:
case ODIV:
case OLDIV:
case OLMOD:
case OLMUL:
case OLSHR:
case OMOD:
case OMUL:
case OOR:
case OSUB:
case OXOR:
case OEQ: // int f(T, T)
case OGE:
case OGT:
case OHI:
case OHS:
case OLE:
case OLO:
case OLS:
case OLT:
case ONE:
if(n->right == Z)
goto bad;
t1 = n->right->type;
if(t1 == T)
goto bad;
if(t1->funct != f)
goto bad;
n->right = new(OLIST, n->left, n->right);
break;
case OAS: // structure copies done by the compiler
case OASI:
goto no;
case OASADD: // T f(T*, T)
case OASAND:
case OASASHL:
case OASASHR:
case OASDIV:
case OASLDIV:
case OASLMOD:
case OASLMUL:
case OASLSHR:
case OASMOD:
case OASMUL:
case OASOR:
case OASSUB:
case OASXOR:
if(n->right == Z)
goto bad;
t1 = n->right->type;
if(t1 == T)
goto bad;
if(t1->funct != f)
goto bad;
n->right = new(OLIST, new(OADDR, n->left, Z), n->right);
break;
case OPOS: // T f(T)
case ONEG:
case ONOT:
case OCOM:
n->right = n->left;
break;
}
build:
l = new(ONAME, Z, Z);
l->sym = s;
l->type = s->type;
l->etype = s->type->etype;
l->xoffset = s->offset;
l->class = s->class;
tcomo(l, 0);
n->op = OFUNC;
n->left = l;
n->type = l->type->link;
if(tcompat(n, T, l->type, tfunct))
goto bad;
if(tcoma(n->left, n->right, l->type->down, 1))
goto bad;
return 1;
no:
return 0;
bad:
diag(n, "cant rewrite typestr for op %O\n", o);
prtree(n, "isfunct");
n->type = T;
return 1;
}
void
dclfunct(Type *t, Sym *s)
{
Funct *f;
Node *n;
Type *f1, *f2, *f3, *f4;
int o, i, c;
char str[100];
if(t->funct)
return;
// recognize generated tag of dorm _%d_
if(t->tag == S)
goto bad;
for(i=0; c = t->tag->name[i]; i++) {
if(c == '_') {
if(i == 0 || t->tag->name[i+1] == 0)
continue;
break;
}
if(c < '0' || c > '9')
break;
}
if(c == 0)
goto bad;
f = alloc(sizeof(*f));
for(o=0; o<sizeof(f->sym); o++)
f->sym[o] = S;
t->funct = f;
f1 = typ(TFUNC, t);
f1->down = copytyp(t);
f1->down->down = t;
f2 = typ(TFUNC, types[TINT]);
f2->down = copytyp(t);
f2->down->down = t;
f3 = typ(TFUNC, t);
f3->down = typ(TIND, t);
f3->down->down = t;
f4 = typ(TFUNC, t);
f4->down = t;
for(i=0;; i++) {
o = ftabinit[i].op;
if(o == OXXX)
break;
sprint(str, "%s_%s_", t->tag->name, ftabinit[i].name);
n = new(ONAME, Z, Z);
n->sym = slookup(str);
f->sym[o] = n->sym;
switch(ftabinit[i].typ) {
default:
diag(Z, "dclfunct op missing %d\n", ftabinit[i].typ);
break;
case 1: // T f(T,T) +
dodecl(xdecl, CEXTERN, f1, n);
break;
case 2: // int f(T,T) ==
dodecl(xdecl, CEXTERN, f2, n);
break;
case 3: // void f(T*,T) +=
dodecl(xdecl, CEXTERN, f3, n);
break;
case 4: // T f(T) ~
dodecl(xdecl, CEXTERN, f4, n);
break;
}
}
for(i=0;; i++) {
o = gtabinit[i].etype;
if(o == TXXX)
break;
/*
* OCAST types T1 _T2_T1_(T2)
*/
sprint(str, "_%s%s_", gtabinit[i].name, t->tag->name);
n = new(ONAME, Z, Z);
n->sym = slookup(str);
f->castto[o] = n->sym;
f1 = typ(TFUNC, t);
f1->down = types[o];
dodecl(xdecl, CEXTERN, f1, n);
sprint(str, "%s_%s_", t->tag->name, gtabinit[i].name);
n = new(ONAME, Z, Z);
n->sym = slookup(str);
f->castfr[o] = n->sym;
f1 = typ(TFUNC, types[o]);
f1->down = t;
dodecl(xdecl, CEXTERN, f1, n);
}
return;
bad:
diag(Z, "dclfunct bad %T %s\n", t, s->name);
}
Gtab gtabinit[NTYPE] =
{
TCHAR, "c",
TUCHAR, "uc",
TSHORT, "h",
TUSHORT, "uh",
TINT, "i",
TUINT, "ui",
TLONG, "l",
TULONG, "ul",
TVLONG, "v",
TUVLONG, "uv",
TFLOAT, "f",
TDOUBLE, "d",
TXXX
};
Ftab ftabinit[OEND] =
{
OADD, "add", 1,
OAND, "and", 1,
OASHL, "ashl", 1,
OASHR, "ashr", 1,
ODIV, "div", 1,
OLDIV, "ldiv", 1,
OLMOD, "lmod", 1,
OLMUL, "lmul", 1,
OLSHR, "lshr", 1,
OMOD, "mod", 1,
OMUL, "mul", 1,
OOR, "or", 1,
OSUB, "sub", 1,
OXOR, "xor", 1,
OEQ, "eq", 2,
OGE, "ge", 2,
OGT, "gt", 2,
OHI, "hi", 2,
OHS, "hs", 2,
OLE, "le", 2,
OLO, "lo", 2,
OLS, "ls", 2,
OLT, "lt", 2,
ONE, "ne", 2,
OASADD, "asadd", 3,
OASAND, "asand", 3,
OASASHL, "asashl", 3,
OASASHR, "asashr", 3,
OASDIV, "asdiv", 3,
OASLDIV, "asldiv", 3,
OASLMOD, "aslmod", 3,
OASLMUL, "aslmul", 3,
OASLSHR, "aslshr", 3,
OASMOD, "asmod", 3,
OASMUL, "asmul", 3,
OASOR, "asor", 3,
OASSUB, "assub", 3,
OASXOR, "asxor", 3,
OPOS, "pos", 4,
ONEG, "neg", 4,
OCOM, "com", 4,
ONOT, "not", 4,
// OPOSTDEC,
// OPOSTINC,
// OPREDEC,
// OPREINC,
OXXX,
};
// Node* nodtestv;
// Node* nodvpp;
// Node* nodppv;
// Node* nodvmm;
// Node* nodmmv;