diff options
Diffstat (limited to 'src/cmd/cc/funct.c')
-rw-r--r-- | src/cmd/cc/funct.c | 431 |
1 files changed, 431 insertions, 0 deletions
diff --git a/src/cmd/cc/funct.c b/src/cmd/cc/funct.c new file mode 100644 index 000000000..99477b2b2 --- /dev/null +++ b/src/cmd/cc/funct.c @@ -0,0 +1,431 @@ +// Inferno utils/cc/funct.c +// http://code.google.com/p/inferno-os/source/browse/utils/cc/funct.c +// +// Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. +// Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) +// Portions Copyright © 1997-1999 Vita Nuova Limited +// Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) +// Portions Copyright © 2004,2006 Bruce Ellis +// Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) +// Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others +// Portions Copyright © 2009 The Go Authors. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include <u.h> +#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; |