diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/cc/funct.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/cc/funct.c')
-rwxr-xr-x | sys/src/cmd/cc/funct.c | 400 |
1 files changed, 400 insertions, 0 deletions
diff --git a/sys/src/cmd/cc/funct.c b/sys/src/cmd/cc/funct.c new file mode 100755 index 000000000..3a236be31 --- /dev/null +++ b/sys/src/cmd/cc/funct.c @@ -0,0 +1,400 @@ +#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; |