![cinap_lenrek](/assets/img/avatar_default.png)
slookup() copies to symb, so use the symb[NSYMB] buffer directly to declare type conversion functions and get rid of the arbitrary sized local buffer. replace sprint() with snprint().
400 lines
6 KiB
C
400 lines
6 KiB
C
#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;
|
|
|
|
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<nelem(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;
|
|
snprint(symb, NSYMB, "%s_%s_", t->tag->name, ftabinit[i].name);
|
|
n = new(ONAME, Z, Z);
|
|
n->sym = lookup();
|
|
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)
|
|
*/
|
|
snprint(symb, NSYMB, "_%s%s_", gtabinit[i].name, t->tag->name);
|
|
n = new(ONAME, Z, Z);
|
|
n->sym = lookup();
|
|
f->castto[o] = n->sym;
|
|
|
|
f1 = typ(TFUNC, t);
|
|
f1->down = types[o];
|
|
dodecl(xdecl, CEXTERN, f1, n);
|
|
|
|
snprint(symb, NSYMB, "%s_%s_", t->tag->name, gtabinit[i].name);
|
|
n = new(ONAME, Z, Z);
|
|
n->sym = lookup();
|
|
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;
|