diff options
author | Ondřej Surý <ondrej@sury.org> | 2012-04-06 15:14:11 +0200 |
---|---|---|
committer | Ondřej Surý <ondrej@sury.org> | 2012-04-06 15:14:11 +0200 |
commit | 505c19580e0f43fe5224431459cacb7c21edd93d (patch) | |
tree | 79e2634c253d60afc0cc0b2f510dc7dcbb48497b /src/cmd/8g | |
parent | 1336a7c91e596c423a49d1194ea42d98bca0d958 (diff) | |
download | golang-505c19580e0f43fe5224431459cacb7c21edd93d.tar.gz |
Imported Upstream version 1upstream/1
Diffstat (limited to 'src/cmd/8g')
-rw-r--r-- | src/cmd/8g/Makefile | 35 | ||||
-rw-r--r-- | src/cmd/8g/cgen.c | 42 | ||||
-rw-r--r-- | src/cmd/8g/cgen64.c | 2 | ||||
-rw-r--r-- | src/cmd/8g/doc.go | 2 | ||||
-rw-r--r-- | src/cmd/8g/galign.c | 2 | ||||
-rw-r--r-- | src/cmd/8g/gg.h | 24 | ||||
-rw-r--r-- | src/cmd/8g/ggen.c | 26 | ||||
-rw-r--r-- | src/cmd/8g/gobj.c | 66 | ||||
-rw-r--r-- | src/cmd/8g/gsubr.c | 83 | ||||
-rw-r--r-- | src/cmd/8g/list.c | 4 | ||||
-rw-r--r-- | src/cmd/8g/opt.h | 2 | ||||
-rw-r--r-- | src/cmd/8g/peep.c | 5 | ||||
-rw-r--r-- | src/cmd/8g/reg.c | 188 |
13 files changed, 320 insertions, 161 deletions
diff --git a/src/cmd/8g/Makefile b/src/cmd/8g/Makefile index b459782a3..3f528d751 100644 --- a/src/cmd/8g/Makefile +++ b/src/cmd/8g/Makefile @@ -1,36 +1,5 @@ -# Copyright 2009 The Go Authors. All rights reserved. +# Copyright 2012 The Go Authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. -include ../../Make.inc -O:=$(HOST_O) - -TARG=8g - -HFILES=\ - ../gc/go.h\ - ../8l/8.out.h\ - gg.h\ - opt.h\ - -OFILES=\ - ../8l/enam.$O\ - cgen.$O\ - cgen64.$O\ - cplx.$O\ - galign.$O\ - ggen.$O\ - gobj.$O\ - gsubr.$O\ - list.$O\ - peep.$O\ - pgen.$O\ - reg.$O\ - -LIB=\ - ../gc/gc.a\ - -include ../../Make.ccmd - -%.$O: ../gc/%.c - $(HOST_CC) $(HOST_CFLAGS) -c -I. -o $@ ../gc/$*.c +include ../../Make.dist diff --git a/src/cmd/8g/cgen.c b/src/cmd/8g/cgen.c index b316e6e34..48619ac73 100644 --- a/src/cmd/8g/cgen.c +++ b/src/cmd/8g/cgen.c @@ -5,6 +5,8 @@ // TODO(rsc): // assume CLD? +#include <u.h> +#include <libc.h> #include "gg.h" void @@ -96,6 +98,9 @@ cgen(Node *n, Node *res) if(isslice(n->left->type)) n->addable = n->left->addable; break; + case OITAB: + n->addable = n->left->addable; + break; } // if both are addressable, move @@ -250,6 +255,13 @@ cgen(Node *n, Node *res) regfree(&n1); break; + case OITAB: + igen(nl, &n1, res); + n1.type = ptrto(types[TUINTPTR]); + gmove(&n1, res); + regfree(&n1); + break; + case OLEN: if(istype(nl->type, TMAP) || istype(nl->type, TCHAN)) { // map has len in the first 32-bit word. @@ -680,7 +692,6 @@ agen(Node *n, Node *res) break; case ODOT: - t = nl->type; agen(nl, res); if(n->xoffset != 0) { nodconst(&n1, types[tptr], n->xoffset); @@ -786,6 +797,7 @@ bgen(Node *n, int true, Prog *to) int et, a; Node *nl, *nr, *r; Node n1, n2, tmp, t1, t2, ax; + NodeList *ll; Prog *p1, *p2; if(debug['g']) { @@ -798,9 +810,6 @@ bgen(Node *n, int true, Prog *to) if(n->ninit != nil) genlist(n->ninit); - nl = n->left; - nr = n->right; - if(n->type == T) { convlit(&n, types[TBOOL]); if(n->type == T) @@ -813,7 +822,6 @@ bgen(Node *n, int true, Prog *to) patch(gins(AEND, N, N), to); return; } - nl = N; nr = N; switch(n->op) { @@ -905,7 +913,10 @@ bgen(Node *n, int true, Prog *to) p1 = gbranch(AJMP, T); p2 = gbranch(AJMP, T); patch(p1, pc); + ll = n->ninit; // avoid re-genning ninit + n->ninit = nil; bgen(n, 1, p2); + n->ninit = ll; patch(gbranch(AJMP, T), to); patch(p2, pc); break; @@ -1129,24 +1140,29 @@ stkof(Node *n) * memmove(&res, &n, w); */ void -sgen(Node *n, Node *res, int32 w) +sgen(Node *n, Node *res, int64 w) { Node dst, src, tdst, tsrc; int32 c, q, odst, osrc; if(debug['g']) { - print("\nsgen w=%d\n", w); + print("\nsgen w=%lld\n", w); dump("r", n); dump("res", res); } - if(w == 0) - return; - if(n->ullman >= UINF && res->ullman >= UINF) { + if(n->ullman >= UINF && res->ullman >= UINF) fatal("sgen UINF"); - } - if(w < 0) - fatal("sgen copy %d", w); + if(w < 0 || (int32)w != w) + fatal("sgen copy %lld", w); + + if(w == 0) { + // evaluate side effects only. + tempname(&tdst, types[tptr]); + agen(res, &tdst); + agen(n, &tdst); + return; + } // offset on the stack osrc = stkof(n); diff --git a/src/cmd/8g/cgen64.c b/src/cmd/8g/cgen64.c index ba99cec74..8e568a0f9 100644 --- a/src/cmd/8g/cgen64.c +++ b/src/cmd/8g/cgen64.c @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +#include <u.h> +#include <libc.h> #include "gg.h" /* diff --git a/src/cmd/8g/doc.go b/src/cmd/8g/doc.go index 2d9ff9a42..6d678eac8 100644 --- a/src/cmd/8g/doc.go +++ b/src/cmd/8g/doc.go @@ -9,7 +9,5 @@ The $GOARCH for these tools is 386. It reads .go files and outputs .8 files. The flags are documented in ../gc/doc.go. -There is no instruction optimizer, so the -N flag is a no-op. - */ package documentation diff --git a/src/cmd/8g/galign.c b/src/cmd/8g/galign.c index 7734603c4..4526a2efb 100644 --- a/src/cmd/8g/galign.c +++ b/src/cmd/8g/galign.c @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +#include <u.h> +#include <libc.h> #include "gg.h" int thechar = '8'; diff --git a/src/cmd/8g/gg.h b/src/cmd/8g/gg.h index 9f7a66a29..0a4f0ad2d 100644 --- a/src/cmd/8g/gg.h +++ b/src/cmd/8g/gg.h @@ -2,16 +2,13 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -#include <u.h> -#include <libc.h> - -#include "../gc/go.h" -#include "../8l/8.out.h" - #ifndef EXTERN #define EXTERN extern #endif +#include "../gc/go.h" +#include "../8l/8.out.h" + typedef struct Addr Addr; struct Addr @@ -46,6 +43,8 @@ struct Prog void* reg; // pointer to containing Reg struct }; +#define TEXTFLAG from.scale + // foptoas flags enum { @@ -54,15 +53,12 @@ enum Fpop2 = 1<<2, }; -EXTERN Biobuf* bout; EXTERN int32 dynloc; EXTERN uchar reg[D_NONE]; EXTERN int32 pcloc; // instruction counter EXTERN Strlit emptystring; extern char* anames[]; -EXTERN Hist* hist; EXTERN Prog zprog; -EXTERN Node* curfn; EXTERN Node* newproc; EXTERN Node* deferproc; EXTERN Node* deferreturn; @@ -103,7 +99,7 @@ void agenr(Node *n, Node *a, Node *res); void igen(Node*, Node*, Node*); vlong fieldoffset(Type*, Node*); void bgen(Node*, int, Prog*); -void sgen(Node*, Node*, int32); +void sgen(Node*, Node*, int64); void gmove(Node*, Node*); Prog* gins(int, Node*, Node*); int samaddr(Node*, Node*); @@ -168,12 +164,6 @@ void complexgen(Node*, Node*); void complexbool(int, Node*, Node*, int, Prog*); /* - * gobj.c - */ -void data(void); -void text(void); - -/* * list.c */ int Aconv(Fmt*); @@ -185,3 +175,5 @@ void listinit(void); void zaddr(Biobuf*, Addr*, int, int); +#pragma varargck type "D" Addr* +#pragma varargck type "lD" Addr* diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c index 108c493aa..6a4570199 100644 --- a/src/cmd/8g/ggen.c +++ b/src/cmd/8g/ggen.c @@ -4,6 +4,8 @@ #undef EXTERN #define EXTERN +#include <u.h> +#include <libc.h> #include "gg.h" #include "opt.h" @@ -26,10 +28,10 @@ markautoused(Prog* p) { for (; p; p = p->link) { if (p->from.type == D_AUTO && p->from.node) - p->from.node->used++; + p->from.node->used = 1; if (p->to.type == D_AUTO && p->to.node) - p->to.node->used++; + p->to.node->used = 1; } } @@ -429,7 +431,6 @@ hard: if(nr->ullman >= nl->ullman || nl->addable) { mgen(nr, &n2, N); nr = &n2; - nr = &n2; } else { tempname(&n2, nr->type); cgen(nr, &n2); @@ -483,8 +484,8 @@ void dodiv(int op, Node *nl, Node *nr, Node *res, Node *ax, Node *dx) { int check; - Node n1, t1, t2, n4, nz; - Type *t; + Node n1, t1, t2, t3, t4, n4, nz; + Type *t, *t0; Prog *p1, *p2, *p3; // Have to be careful about handling @@ -496,6 +497,7 @@ dodiv(int op, Node *nl, Node *nr, Node *res, Node *ax, Node *dx) // For int32 and int64, use explicit test. // Could use int64 hw for int32. t = nl->type; + t0 = t; check = 0; if(issigned[t->etype]) { check = 1; @@ -514,8 +516,18 @@ dodiv(int op, Node *nl, Node *nr, Node *res, Node *ax, Node *dx) tempname(&t1, t); tempname(&t2, t); - cgen(nl, &t1); - cgen(nr, &t2); + if(t0 != t) { + tempname(&t3, t0); + tempname(&t4, t0); + cgen(nl, &t3); + cgen(nr, &t4); + // Convert. + gmove(&t3, &t1); + gmove(&t4, &t2); + } else { + cgen(nl, &t1); + cgen(nr, &t2); + } if(!samereg(ax, res) && !samereg(dx, res)) regalloc(&n1, t, res); diff --git a/src/cmd/8g/gobj.c b/src/cmd/8g/gobj.c index 31c42a3f2..d8c8f5ab9 100644 --- a/src/cmd/8g/gobj.c +++ b/src/cmd/8g/gobj.c @@ -28,6 +28,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +#include <u.h> +#include <libc.h> #include "gg.h" void @@ -276,54 +278,6 @@ dumpfuncs(void) } } -/* deferred DATA output */ -static Prog *strdat; -static Prog *estrdat; -static int gflag; -static Prog *savepc; - -void -data(void) -{ - gflag = debug['g']; - debug['g'] = 0; - - if(estrdat == nil) { - strdat = mal(sizeof(*pc)); - clearp(strdat); - estrdat = strdat; - } - if(savepc) - fatal("data phase error"); - savepc = pc; - pc = estrdat; -} - -void -text(void) -{ - if(!savepc) - fatal("text phase error"); - debug['g'] = gflag; - estrdat = pc; - pc = savepc; - savepc = nil; -} - -void -dumpdata(void) -{ - Prog *p; - - if(estrdat == nil) - return; - *pc = *strdat; - if(gflag) - for(p=pc; p!=estrdat; p=p->link) - print("%P\n", p); - pc = estrdat; -} - int dsname(Sym *s, int off, char *t, int n) { @@ -354,6 +308,7 @@ datastring(char *s, int len, Addr *a) sym = stringsym(s, len); a->type = D_EXTERN; a->sym = sym; + a->node = sym->def; a->offset = widthptr+4; // skip header a->etype = TINT32; } @@ -370,6 +325,7 @@ datagostring(Strlit *sval, Addr *a) sym = stringsym(sval->s, sval->len); a->type = D_EXTERN; a->sym = sym; + a->node = sym->def; a->offset = 0; // header a->etype = TINT32; } @@ -380,6 +336,17 @@ gdata(Node *nam, Node *nr, int wid) Prog *p; vlong v; + if(nr->op == OLITERAL) { + switch(nr->val.ctype) { + case CTCPLX: + gdatacomplex(nam, nr->val.u.cval); + return; + case CTSTR: + gdatastring(nam, nr->val.u.sval); + return; + } + } + if(wid == 8 && is64(nr->type)) { v = mpgetfix(nr->val.u.xval); p = gins(ADATA, nam, nodintconst(v)); @@ -547,6 +514,8 @@ genembedtramp(Type *rcvr, Type *method, Sym *newnam, int iface) Prog *p; Type *f; + USED(iface); + e = method->sym; for(d=0; d<nelem(dotlist); d++) { c = adddot1(e, rcvr, d, nil, 0); @@ -626,7 +595,6 @@ out: // but 6l has a bug, and it can't handle // JMP instructions too close to the top of // a new function. - p = pc; gins(ANOP, N, N); } diff --git a/src/cmd/8g/gsubr.c b/src/cmd/8g/gsubr.c index a35c81eb1..5e89af04a 100644 --- a/src/cmd/8g/gsubr.c +++ b/src/cmd/8g/gsubr.c @@ -28,6 +28,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +#include <u.h> +#include <libc.h> #include "gg.h" // TODO(rsc): Can make this bigger if we move @@ -48,6 +50,10 @@ clearp(Prog *p) 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. @@ -57,10 +63,22 @@ prog(int as) { Prog *p; - p = pc; - pc = mal(sizeof(*pc)); - - clearp(pc); + 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']) @@ -69,10 +87,21 @@ prog(int as) p->as = as; p->lineno = lineno; - p->link = pc; return p; } +void +dumpdata(void) +{ + ddumped = 1; + if(dfirst == nil) + return; + newplist(); + *pc = *dfirst; + pc = dpc; + clearp(pc); +} + /* * generate a branch. * t is ignored. @@ -82,6 +111,7 @@ gbranch(int as, Type *t) { Prog *p; + USED(t); p = prog(as); p->to.type = D_BRANCH; p->to.branch = P; @@ -202,6 +232,8 @@ ggloblnod(Node *nam, int32 width) p->to.offset = width; if(nam->readonly) p->from.scale = RODATA; + if(nam->type != T && !haspointers(nam->type)) + p->from.scale |= NOPTR; } void @@ -753,7 +785,7 @@ ginit(void) reg[resvd[i]]++; } -ulong regpc[D_NONE]; +uintptr regpc[D_NONE]; void gclean(void) @@ -822,7 +854,7 @@ regalloc(Node *n, Type *t, Node *o) fprint(2, "registers allocated at\n"); for(i=D_AX; i<=D_DI; i++) - fprint(2, "\t%R\t%#ux\n", i, regpc[i]); + fprint(2, "\t%R\t%#lux\n", i, regpc[i]); yyerror("out of fixed registers"); goto err; @@ -832,7 +864,6 @@ regalloc(Node *n, Type *t, Node *o) goto out; } yyerror("regalloc: unknown type %T", t); - i = 0; err: nodreg(n, t, 0); @@ -842,7 +873,7 @@ out: if (i == D_SP) print("alloc SP\n"); if(reg[i] == 0) { - regpc[i] = (ulong)__builtin_return_address(0); + regpc[i] = (uintptr)getcallerpc(&n); if(i == D_AX || i == D_CX || i == D_DX || i == D_SP) { dump("regalloc-o", o); fatal("regalloc %R", i); @@ -864,7 +895,7 @@ regfree(Node *n) i = n->val.u.reg; if(i == D_SP) return; - if(i < 0 || i >= sizeof(reg)) + if(i < 0 || i >= nelem(reg)) fatal("regfree: reg out of range"); if(reg[i] <= 0) fatal("regfree: reg not allocated"); @@ -935,8 +966,15 @@ nodarg(Type *t, int fp) fatal("nodarg: offset not computed for %T", t); n->xoffset = t->width; n->addable = 1; + n->orig = t->nname; break; } + + // Rewrite argument named _ to __, + // or else the assignment to _ will be + // discarded during code generation. + if(isblank(n)) + n->sym = lookup("__"); switch(fp) { default: @@ -1005,6 +1043,7 @@ int ismem(Node *n) { switch(n->op) { + case OITAB: case OLEN: case OCAP: case OINDREG: @@ -1123,6 +1162,7 @@ memname(Node *n, Type *t) strcpy(namebuf, n->sym->name); namebuf[0] = '.'; // keep optimizer from registerizing n->sym = lookup(namebuf); + n->orig->sym = n->sym; } void @@ -1799,6 +1839,7 @@ naddr(Node *n, Addr *a, int canemitcode) a->offset = n->xoffset; a->sym = n->left->sym; a->type = D_PARAM; + a->node = n->left->orig; break; case ONAME: @@ -1809,9 +1850,11 @@ naddr(Node *n, Addr *a, int canemitcode) a->width = n->type->width; a->gotype = ngotype(n); } - a->pun = n->pun; a->offset = n->xoffset; a->sym = n->sym; + a->node = n->orig; + //if(a->node >= (Node*)&n) + // fatal("stack node"); if(a->sym == S) a->sym = lookup(".noname"); if(n->method) { @@ -1829,8 +1872,6 @@ naddr(Node *n, Addr *a, int canemitcode) break; case PAUTO: a->type = D_AUTO; - if (n->sym) - a->node = n->orig; break; case PPARAM: case PPARAMOUT: @@ -1853,6 +1894,7 @@ naddr(Node *n, Addr *a, int canemitcode) a->dval = mpgetflt(n->val.u.fval); break; case CTINT: + case CTRUNE: a->sym = S; a->type = D_CONST; a->offset = mpgetfix(n->val.u.xval); @@ -1887,6 +1929,17 @@ naddr(Node *n, Addr *a, int canemitcode) break; } fatal("naddr: OADDR\n"); + + case OITAB: + // itable of interface value + naddr(n->left, a, canemitcode); + if(a->type == D_CONST && a->offset == 0) + break; // len(nil) + a->etype = tptr; + a->width = widthptr; + if(a->offset >= unmappedzero && a->offset-Array_nel < unmappedzero) + checkoffset(a, canemitcode); + break; case OLEN: // len of string or slice @@ -1955,5 +2008,9 @@ sudoclean(void) int sudoaddable(int as, Node *n, Addr *a) { + USED(as); + USED(n); + USED(a); + return 0; } diff --git a/src/cmd/8g/list.c b/src/cmd/8g/list.c index edb1ece84..88d3d5f7e 100644 --- a/src/cmd/8g/list.c +++ b/src/cmd/8g/list.c @@ -28,6 +28,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +#include <u.h> +#include <libc.h> #include "gg.h" static int sconsize; @@ -128,7 +130,7 @@ Dconv(Fmt *fp) if(fp->flags & FmtLong) { d1 = a->offset; d2 = a->offset2; - snprint(str, sizeof(str), "$%ud-%ud", (ulong)d1, (ulong)d2); + snprint(str, sizeof(str), "$%lud-%lud", (ulong)d1, (ulong)d2); break; } snprint(str, sizeof(str), "$%d", a->offset); diff --git a/src/cmd/8g/opt.h b/src/cmd/8g/opt.h index 8f31dec3b..ed6eb15ab 100644 --- a/src/cmd/8g/opt.h +++ b/src/cmd/8g/opt.h @@ -162,3 +162,5 @@ int32 RtoB(int); int32 FtoB(int); int BtoR(int32); int BtoF(int32); + +#pragma varargck type "D" Adr* diff --git a/src/cmd/8g/peep.c b/src/cmd/8g/peep.c index 5ad29e1b2..b8a2825e5 100644 --- a/src/cmd/8g/peep.c +++ b/src/cmd/8g/peep.c @@ -28,6 +28,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +#include <u.h> +#include <libc.h> #include "gg.h" #include "opt.h" @@ -876,13 +878,12 @@ loop: case 3: // set if(p->as == p0->as) if(p->from.type == p0->from.type) - if(p->from.sym == p0->from.sym) + if(p->from.node == p0->from.node) if(p->from.offset == p0->from.offset) if(p->from.scale == p0->from.scale) if(p->from.dval == p0->from.dval) if(p->from.index == p0->from.index) { excise(r); - t++; goto loop; } break; diff --git a/src/cmd/8g/reg.c b/src/cmd/8g/reg.c index 2b878f62a..29270c820 100644 --- a/src/cmd/8g/reg.c +++ b/src/cmd/8g/reg.c @@ -28,9 +28,9 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. +#include <u.h> +#include <libc.h> #include "gg.h" -#undef EXTERN -#define EXTERN #include "opt.h" #define NREGVAR 8 @@ -39,6 +39,8 @@ static int first = 1; +static void fixjmp(Prog*); + Reg* rega(void) { @@ -89,8 +91,8 @@ setoutvar(void) ovar.b[z] |= bit.b[z]; t = structnext(&save); } -//if(bany(b)) -//print("ovars = %Q\n", &ovar); +//if(bany(ovar)) +//print("ovars = %Q\n", ovar); } static void @@ -98,19 +100,19 @@ setaddrs(Bits bit) { int i, n; Var *v; - Sym *s; + Node *node; while(bany(&bit)) { // convert each bit to a variable i = bnum(bit); - s = var[i].sym; + node = var[i].node; n = var[i].name; bit.b[i/32] &= ~(1L<<(i%32)); // disable all pieces of that variable for(i=0; i<nvar; i++) { v = var+i; - if(v->sym == s && v->name == n) + if(v->node == node && v->name == n) v->addr = 2; } } @@ -132,6 +134,8 @@ regopt(Prog *firstp) exregoffset = D_DI; // no externals first = 0; } + + fixjmp(firstp); // count instructions nr = 0; @@ -155,7 +159,7 @@ regopt(Prog *firstp) nvar = NREGVAR; memset(var, 0, NREGVAR*sizeof var[0]); for(i=0; i<NREGVAR; i++) - var[i].sym = lookup(regname[i]); + var[i].node = newname(lookup(regname[i])); regbits = RtoB(D_SP); for(z=0; z<BITS; z++) { @@ -216,6 +220,9 @@ regopt(Prog *firstp) * funny */ case ALEAL: + case AFMOVL: + case AFMOVW: + case AFMOVV: setaddrs(bit); break; @@ -694,9 +701,9 @@ brk: if(ostats.ndelmov) print(" %4d delmov\n", ostats.ndelmov); if(ostats.nvar) - print(" %4d delmov\n", ostats.nvar); + print(" %4d var\n", ostats.nvar); if(ostats.naddr) - print(" %4d delmov\n", ostats.naddr); + print(" %4d addr\n", ostats.naddr); memset(&ostats, 0, sizeof(ostats)); } @@ -725,19 +732,19 @@ addmove(Reg *r, int bn, int rn, int f) v = var + bn; a = &p1->to; - a->sym = v->sym; a->offset = v->offset; a->etype = v->etype; a->type = v->name; a->gotype = v->gotype; a->node = v->node; + a->sym = v->node->sym; // need to clean this up with wptr and // some of the defaults p1->as = AMOVL; switch(v->etype) { default: - fatal("unknown type\n"); + fatal("unknown type %E", v->etype); case TINT8: case TUINT8: case TBOOL: @@ -810,7 +817,7 @@ mkvar(Reg *r, Adr *a) int i, t, n, et, z, w, flag, regu; int32 o; Bits bit; - Sym *s; + Node *node; /* * mark registers used @@ -847,10 +854,13 @@ mkvar(Reg *r, Adr *a) break; } - s = a->sym; - if(s == S) + node = a->node; + if(node == N || node->op != ONAME || node->orig == N) goto none; - if(s->name[0] == '.') + node = node->orig; + if(node->orig != node) + fatal("%D: bad node", a); + if(node->sym == S || node->sym->name[0] == '.') goto none; et = a->etype; o = a->offset; @@ -859,7 +869,7 @@ mkvar(Reg *r, Adr *a) flag = 0; for(i=0; i<nvar; i++) { v = var+i; - if(v->sym == s && v->name == n) { + if(v->node == node && v->name == n) { if(v->offset == o) if(v->etype == et) if(v->width == w) @@ -868,7 +878,7 @@ mkvar(Reg *r, Adr *a) // if they overlap, disable both if(overlap(v->offset, v->width, o, w)) { if(debug['R']) - print("disable %s\n", v->sym->name); + print("disable %s\n", node->sym->name); v->addr = 1; flag = 1; } @@ -882,7 +892,7 @@ mkvar(Reg *r, Adr *a) } if(nvar >= NVAR) { - if(debug['w'] > 1 && s) + if(debug['w'] > 1 && node != N) fatal("variable not optimized: %D", a); goto none; } @@ -890,17 +900,16 @@ mkvar(Reg *r, Adr *a) i = nvar; nvar++; v = var+i; - v->sym = s; v->offset = o; v->name = n; v->gotype = a->gotype; v->etype = et; v->width = w; v->addr = flag; // funny punning - v->node = a->node; + v->node = node; if(debug['R']) - print("bit=%2d et=%2d w=%d+%d %S %D flag=%d\n", i, et, o, w, s, a, v->addr); + print("bit=%2d et=%2d w=%d+%d %#N %D flag=%d\n", i, et, o, w, node, a, v->addr); ostats.nvar++; bit = blsh(i); @@ -959,6 +968,13 @@ prop(Reg *r, Bits ref, Bits cal) ref.b[z] = 0; } break; + + default: + // Work around for issue 1304: + // flush modified globals before each instruction. + for(z=0; z<BITS; z++) + cal.b[z] |= externs.b[z]; + break; } for(z=0; z<BITS; z++) { ref.b[z] = (ref.b[z] & ~r1->set.b[z]) | @@ -1095,10 +1111,12 @@ loopit(Reg *r, int32 nr) r1 = rpo2r[i]; me = r1->rpo; d = -1; - if(r1->p1 != R && r1->p1->rpo < me) + // rpo2r[r->rpo] == r protects against considering dead code, + // which has r->rpo == 0. + if(r1->p1 != R && rpo2r[r1->p1->rpo] == r1->p1 && r1->p1->rpo < me) d = r1->p1->rpo; for(r1 = r1->p2; r1 != nil; r1 = r1->p2link) - if(r1->rpo < me) + if(rpo2r[r1->rpo] == r1 && r1->rpo < me) d = rpolca(idom, d, r1->rpo); idom[i] = d; } @@ -1482,7 +1500,7 @@ dumpone(Reg *r) if(bany(&r->refahead)) print(" ra:%Q ", r->refahead); if(bany(&r->calbehind)) - print("cb:%Q ", r->calbehind); + print(" cb:%Q ", r->calbehind); if(bany(&r->calahead)) print(" ca:%Q ", r->calahead); if(bany(&r->regdiff)) @@ -1542,3 +1560,123 @@ noreturn(Prog *p) return 1; return 0; } + +/* + * the code generator depends on being able to write out JMP + * instructions that it can jump to now but fill in later. + * the linker will resolve them nicely, but they make the code + * longer and more difficult to follow during debugging. + * remove them. + */ + +/* what instruction does a JMP to p eventually land on? */ +static Prog* +chasejmp(Prog *p, int *jmploop) +{ + int n; + + n = 0; + while(p != P && p->as == AJMP && p->to.type == D_BRANCH) { + if(++n > 10) { + *jmploop = 1; + break; + } + p = p->to.branch; + } + return p; +} + +/* + * reuse reg pointer for mark/sweep state. + * leave reg==nil at end because alive==nil. + */ +#define alive ((void*)0) +#define dead ((void*)1) + +/* mark all code reachable from firstp as alive */ +static void +mark(Prog *firstp) +{ + Prog *p; + + for(p=firstp; p; p=p->link) { + if(p->reg != dead) + break; + p->reg = alive; + if(p->as != ACALL && p->to.type == D_BRANCH && p->to.branch) + mark(p->to.branch); + if(p->as == AJMP || p->as == ARET || (p->as == ACALL && noreturn(p))) + break; + } +} + +static void +fixjmp(Prog *firstp) +{ + int jmploop; + Prog *p, *last; + + if(debug['R'] && debug['v']) + print("\nfixjmp\n"); + + // pass 1: resolve jump to AJMP, mark all code as dead. + jmploop = 0; + for(p=firstp; p; p=p->link) { + if(debug['R'] && debug['v']) + print("%P\n", p); + if(p->as != ACALL && p->to.type == D_BRANCH && p->to.branch && p->to.branch->as == AJMP) { + p->to.branch = chasejmp(p->to.branch, &jmploop); + if(debug['R'] && debug['v']) + print("->%P\n", p); + } + p->reg = dead; + } + if(debug['R'] && debug['v']) + print("\n"); + + // pass 2: mark all reachable code alive + mark(firstp); + + // pass 3: delete dead code (mostly JMPs). + last = nil; + for(p=firstp; p; p=p->link) { + if(p->reg == dead) { + if(p->link == P && p->as == ARET && last && last->as != ARET) { + // This is the final ARET, and the code so far doesn't have one. + // Let it stay. + } else { + if(debug['R'] && debug['v']) + print("del %P\n", p); + continue; + } + } + if(last) + last->link = p; + last = p; + } + last->link = P; + + // pass 4: elide JMP to next instruction. + // only safe if there are no jumps to JMPs anymore. + if(!jmploop) { + last = nil; + for(p=firstp; p; p=p->link) { + if(p->as == AJMP && p->to.type == D_BRANCH && p->to.branch == p->link) { + if(debug['R'] && debug['v']) + print("del %P\n", p); + continue; + } + if(last) + last->link = p; + last = p; + } + last->link = P; + } + + if(debug['R'] && debug['v']) { + print("\n"); + for(p=firstp; p; p=p->link) + print("%P\n", p); + print("\n"); + } +} |