diff options
Diffstat (limited to 'src/cmd/gc/gsubr.c')
-rw-r--r-- | src/cmd/gc/gsubr.c | 654 |
1 files changed, 0 insertions, 654 deletions
diff --git a/src/cmd/gc/gsubr.c b/src/cmd/gc/gsubr.c deleted file mode 100644 index 5175ae34f5..0000000000 --- a/src/cmd/gc/gsubr.c +++ /dev/null @@ -1,654 +0,0 @@ -// Derived from Inferno utils/6c/txt.c -// http://code.google.com/p/inferno-os/source/browse/utils/6c/txt.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 <libc.h> -#include "go.h" -#include "../../runtime/funcdata.h" -#include "../ld/textflag.h" - -void -ggloblnod(Node *nam) -{ - Prog *p; - - p = thearch.gins(AGLOBL, nam, N); - p->lineno = nam->lineno; - p->from.sym->gotype = linksym(ngotype(nam)); - p->to.sym = nil; - p->to.type = TYPE_CONST; - p->to.offset = nam->type->width; - if(nam->readonly) - p->from3.offset = RODATA; - if(nam->type != T && !haspointers(nam->type)) - p->from3.offset |= NOPTR; -} - -void -gtrack(Sym *s) -{ - Prog *p; - - p = thearch.gins(AUSEFIELD, N, N); - p->from.type = TYPE_MEM; - p->from.name = NAME_EXTERN; - p->from.sym = linksym(s); -} - -void -ggloblsym(Sym *s, int32 width, int8 flags) -{ - Prog *p; - - p = thearch.gins(AGLOBL, N, N); - p->from.type = TYPE_MEM; - p->from.name = NAME_EXTERN; - p->from.sym = linksym(s); - p->to.type = TYPE_CONST; - p->to.offset = width; - p->from3.offset = flags; -} - -void -clearp(Prog *p) -{ - nopout(p); - p->as = AEND; - p->pc = pcloc; - pcloc++; -} - -static int ddumped; -static Prog *dfirst; -static Prog *dpc; - -/* - * generate and return proc with p->as = as, - * linked into program. pc is next instruction. - */ -Prog* -prog(int as) -{ - Prog *p; - - if(as == ADATA || as == AGLOBL) { - if(ddumped) - fatal("already dumped data"); - if(dpc == nil) { - dpc = mal(sizeof(*dpc)); - dfirst = dpc; - } - p = dpc; - dpc = mal(sizeof(*dpc)); - p->link = dpc; - } else { - p = pc; - pc = mal(sizeof(*pc)); - clearp(pc); - p->link = pc; - } - - if(lineno == 0) { - if(debug['K']) - warn("prog: line 0"); - } - - p->as = as; - p->lineno = lineno; - return p; -} - -void -dumpdata(void) -{ - ddumped = 1; - if(dfirst == nil) - return; - newplist(); - *pc = *dfirst; - pc = dpc; - clearp(pc); -} - -/* - * generate a branch. - * t is ignored. - * likely values are for branch prediction: - * -1 unlikely - * 0 no opinion - * +1 likely - */ -Prog* -gbranch(int as, Type *t, int likely) -{ - Prog *p; - - USED(t); - - p = prog(as); - p->to.type = TYPE_BRANCH; - p->to.u.branch = P; - if(as != AJMP && likely != 0 && thearch.thechar != '9') { - p->from.type = TYPE_CONST; - p->from.offset = likely > 0; - } - return p; -} - -/* - * patch previous branch to jump to to. - */ -void -patch(Prog *p, Prog *to) -{ - if(p->to.type != TYPE_BRANCH) - fatal("patch: not a branch"); - p->to.u.branch = to; - p->to.offset = to->pc; -} - -Prog* -unpatch(Prog *p) -{ - Prog *q; - - if(p->to.type != TYPE_BRANCH) - fatal("unpatch: not a branch"); - q = p->to.u.branch; - p->to.u.branch = P; - p->to.offset = 0; - return q; -} - -/* - * start a new Prog list. - */ -Plist* -newplist(void) -{ - Plist *pl; - - pl = linknewplist(ctxt); - - pc = mal(sizeof(*pc)); - clearp(pc); - pl->firstpc = pc; - - return pl; -} - -void -gused(Node *n) -{ - thearch.gins(ANOP, n, N); // used -} - -Prog* -gjmp(Prog *to) -{ - Prog *p; - - p = gbranch(AJMP, T, 0); - if(to != P) - patch(p, to); - return p; -} - -int -isfat(Type *t) -{ - if(t != T) - switch(t->etype) { - case TSTRUCT: - case TARRAY: - case TSTRING: - case TINTER: // maybe remove later - return 1; - } - return 0; -} - -/* - * naddr of func generates code for address of func. - * if using opcode that can take address implicitly, - * call afunclit to fix up the argument. - */ -void -afunclit(Addr *a, Node *n) -{ - if(a->type == TYPE_ADDR && a->name == NAME_EXTERN) { - a->type = TYPE_MEM; - a->sym = linksym(n->sym); - } -} - -/* - * initialize n to be register r of type t. - */ -void -nodreg(Node *n, Type *t, int r) -{ - if(t == T) - fatal("nodreg: t nil"); - - memset(n, 0, sizeof(*n)); - n->op = OREGISTER; - n->addable = 1; - ullmancalc(n); - n->val.u.reg = r; - n->type = t; -} - -/* - * initialize n to be indirect of register r; n is type t. - */ -void -nodindreg(Node *n, Type *t, int r) -{ - nodreg(n, t, r); - n->op = OINDREG; -} - -/* - * Is this node a memory operand? - */ -int -ismem(Node *n) -{ - switch(n->op) { - case OITAB: - case OSPTR: - case OLEN: - case OCAP: - case OINDREG: - case ONAME: - case OPARAM: - case OCLOSUREVAR: - return 1; - case OADDR: - return thearch.thechar == '6' || thearch.thechar == '9'; // because 6g uses PC-relative addressing; TODO(rsc): not sure why 9g too - } - return 0; -} - -// Sweep the prog list to mark any used nodes. -void -markautoused(Prog* p) -{ - for (; p; p = p->link) { - if (p->as == ATYPE || p->as == AVARDEF || p->as == AVARKILL) - continue; - - if (p->from.node) - ((Node*)(p->from.node))->used = 1; - - if (p->to.node) - ((Node*)(p->to.node))->used = 1; - } -} - -// Fixup instructions after allocauto (formerly compactframe) has moved all autos around. -void -fixautoused(Prog *p) -{ - Prog **lp; - - for (lp=&p; (p=*lp) != P; ) { - if (p->as == ATYPE && p->from.node && p->from.name == NAME_AUTO && !((Node*)(p->from.node))->used) { - *lp = p->link; - continue; - } - if ((p->as == AVARDEF || p->as == AVARKILL) && p->to.node && !((Node*)(p->to.node))->used) { - // Cannot remove VARDEF instruction, because - unlike TYPE handled above - - // VARDEFs are interspersed with other code, and a jump might be using the - // VARDEF as a target. Replace with a no-op instead. A later pass will remove - // the no-ops. - nopout(p); - continue; - } - if (p->from.name == NAME_AUTO && p->from.node) - p->from.offset += ((Node*)(p->from.node))->stkdelta; - - if (p->to.name == NAME_AUTO && p->to.node) - p->to.offset += ((Node*)(p->to.node))->stkdelta; - - lp = &p->link; - } -} - -int -samereg(Node *a, Node *b) -{ - if(a == N || b == N) - return 0; - if(a->op != OREGISTER) - return 0; - if(b->op != OREGISTER) - return 0; - if(a->val.u.reg != b->val.u.reg) - return 0; - return 1; -} - -Node* -nodarg(Type *t, int fp) -{ - Node *n; - NodeList *l; - Type *first; - Iter savet; - - // entire argument struct, not just one arg - if(t->etype == TSTRUCT && t->funarg) { - n = nod(ONAME, N, N); - n->sym = lookup(".args"); - n->type = t; - first = structfirst(&savet, &t); - if(first == nil) - fatal("nodarg: bad struct"); - if(first->width == BADWIDTH) - fatal("nodarg: offset not computed for %T", t); - n->xoffset = first->width; - n->addable = 1; - goto fp; - } - - if(t->etype != TFIELD) - fatal("nodarg: not field %T", t); - - if(fp == 1) { - for(l=curfn->dcl; l; l=l->next) { - n = l->n; - if((n->class == PPARAM || n->class == PPARAMOUT) && !isblanksym(t->sym) && n->sym == t->sym) - return n; - } - } - - n = nod(ONAME, N, N); - n->type = t->type; - n->sym = t->sym; - - if(t->width == BADWIDTH) - fatal("nodarg: offset not computed for %T", t); - n->xoffset = t->width; - n->addable = 1; - n->orig = t->nname; - -fp: - // Rewrite argument named _ to __, - // or else the assignment to _ will be - // discarded during code generation. - if(isblank(n)) - n->sym = lookup("__"); - - switch(fp) { - case 0: // output arg - n->op = OINDREG; - n->val.u.reg = thearch.REGSP; - if(thearch.thechar == '5') - n->xoffset += 4; - if(thearch.thechar == '9') - n->xoffset += 8; - break; - - case 1: // input arg - n->class = PPARAM; - break; - - case 2: // offset output arg -fatal("shouldn't be used"); - n->op = OINDREG; - n->val.u.reg = thearch.REGSP; - n->xoffset += types[tptr]->width; - break; - } - n->typecheck = 1; - return n; -} - -/* - * generate code to compute n; - * make a refer to result. - */ -void -naddr(Node *n, Addr *a, int canemitcode) -{ - Sym *s; - - *a = zprog.from; - if(n == N) - return; - - if(n->type != T && n->type->etype != TIDEAL) { - // TODO(rsc): This is undone by the selective clearing of width below, - // to match architectures that were not as aggressive in setting width - // during naddr. Those widths must be cleared to avoid triggering - // failures in gins when it detects real but heretofore latent (and one - // hopes innocuous) type mismatches. - // The type mismatches should be fixed and the clearing below removed. - dowidth(n->type); - a->width = n->type->width; - } - - switch(n->op) { - default: - fatal("naddr: bad %O %D", n->op, a); - break; - - case OREGISTER: - a->type = TYPE_REG; - a->reg = n->val.u.reg; - a->sym = nil; - if(thearch.thechar == '8') // TODO(rsc): Never clear a->width. - a->width = 0; - break; - - case OINDREG: - a->type = TYPE_MEM; - a->reg = n->val.u.reg; - a->sym = linksym(n->sym); - a->offset = n->xoffset; - if(a->offset != (int32)a->offset) - yyerror("offset %lld too large for OINDREG", a->offset); - if(thearch.thechar == '8') // TODO(rsc): Never clear a->width. - a->width = 0; - break; - - case OPARAM: - // n->left is PHEAP ONAME for stack parameter. - // compute address of actual parameter on stack. - a->etype = simtype[n->left->type->etype]; - a->width = n->left->type->width; - a->offset = n->xoffset; - a->sym = linksym(n->left->sym); - a->type = TYPE_MEM; - a->name = NAME_PARAM; - a->node = n->left->orig; - break; - - case OCLOSUREVAR: - if(!curfn->needctxt) - fatal("closurevar without needctxt"); - a->type = TYPE_MEM; - a->reg = thearch.REGCTXT; - a->sym = nil; - a->offset = n->xoffset; - break; - - case OCFUNC: - naddr(n->left, a, canemitcode); - a->sym = linksym(n->left->sym); - break; - - case ONAME: - a->etype = 0; - if(n->type != T) - a->etype = simtype[n->type->etype]; - a->offset = n->xoffset; - s = n->sym; - a->node = n->orig; - //if(a->node >= (Node*)&n) - // fatal("stack node"); - if(s == S) - s = lookup(".noname"); - if(n->method) { - if(n->type != T) - if(n->type->sym != S) - if(n->type->sym->pkg != nil) - s = pkglookup(s->name, n->type->sym->pkg); - } - - a->type = TYPE_MEM; - switch(n->class) { - default: - fatal("naddr: ONAME class %S %d\n", n->sym, n->class); - case PEXTERN: - a->name = NAME_EXTERN; - break; - case PAUTO: - a->name = NAME_AUTO; - break; - case PPARAM: - case PPARAMOUT: - a->name = NAME_PARAM; - break; - case PFUNC: - a->name = NAME_EXTERN; - a->type = TYPE_ADDR; - a->width = widthptr; - s = funcsym(s); - break; - } - a->sym = linksym(s); - break; - - case OLITERAL: - if(thearch.thechar == '8') - a->width = 0; - switch(n->val.ctype) { - default: - fatal("naddr: const %lT", n->type); - break; - case CTFLT: - a->type = TYPE_FCONST; - a->u.dval = mpgetflt(n->val.u.fval); - break; - case CTINT: - case CTRUNE: - a->sym = nil; - a->type = TYPE_CONST; - a->offset = mpgetfix(n->val.u.xval); - break; - case CTSTR: - datagostring(n->val.u.sval, a); - break; - case CTBOOL: - a->sym = nil; - a->type = TYPE_CONST; - a->offset = n->val.u.bval; - break; - case CTNIL: - a->sym = nil; - a->type = TYPE_CONST; - a->offset = 0; - break; - } - break; - - case OADDR: - naddr(n->left, a, canemitcode); - a->etype = tptr; - if(thearch.thechar != '5' && thearch.thechar != '9') // TODO(rsc): Do this even for arm, ppc64. - a->width = widthptr; - if(a->type != TYPE_MEM) - fatal("naddr: OADDR %D (from %O)", a, n->left->op); - a->type = TYPE_ADDR; - break; - - case OITAB: - // itable of interface value - naddr(n->left, a, canemitcode); - if(a->type == TYPE_CONST && a->offset == 0) - break; // itab(nil) - a->etype = tptr; - a->width = widthptr; - break; - - case OSPTR: - // pointer in a string or slice - naddr(n->left, a, canemitcode); - if(a->type == TYPE_CONST && a->offset == 0) - break; // ptr(nil) - a->etype = simtype[tptr]; - a->offset += Array_array; - a->width = widthptr; - break; - - case OLEN: - // len of string or slice - naddr(n->left, a, canemitcode); - if(a->type == TYPE_CONST && a->offset == 0) - break; // len(nil) - a->etype = simtype[TUINT]; - if(thearch.thechar == '9') - a->etype = simtype[TINT]; - a->offset += Array_nel; - if(thearch.thechar != '5') // TODO(rsc): Do this even on arm. - a->width = widthint; - break; - - case OCAP: - // cap of string or slice - naddr(n->left, a, canemitcode); - if(a->type == TYPE_CONST && a->offset == 0) - break; // cap(nil) - a->etype = simtype[TUINT]; - if(thearch.thechar == '9') - a->etype = simtype[TINT]; - a->offset += Array_cap; - if(thearch.thechar != '5') // TODO(rsc): Do this even on arm. - a->width = widthint; - break; - -// case OADD: -// if(n->right->op == OLITERAL) { -// v = n->right->vconst; -// naddr(n->left, a, canemitcode); -// } else -// if(n->left->op == OLITERAL) { -// v = n->left->vconst; -// naddr(n->right, a, canemitcode); -// } else -// goto bad; -// a->offset += v; -// break; - - } -} |