summaryrefslogtreecommitdiff
path: root/src/cmd/5g
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/5g')
-rw-r--r--src/cmd/5g/Makefile35
-rw-r--r--src/cmd/5g/cgen.c68
-rw-r--r--src/cmd/5g/cgen64.c12
-rw-r--r--src/cmd/5g/doc.go2
-rw-r--r--src/cmd/5g/galign.c2
-rw-r--r--src/cmd/5g/gg.h21
-rw-r--r--src/cmd/5g/ggen.c9
-rw-r--r--src/cmd/5g/gobj.c63
-rw-r--r--src/cmd/5g/gsubr.c94
-rw-r--r--src/cmd/5g/list.c4
-rw-r--r--src/cmd/5g/peep.c10
-rw-r--r--src/cmd/5g/reg.c177
12 files changed, 339 insertions, 158 deletions
diff --git a/src/cmd/5g/Makefile b/src/cmd/5g/Makefile
index b47014a4e..3f528d751 100644
--- a/src/cmd/5g/Makefile
+++ b/src/cmd/5g/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=5g
-
-HFILES=\
- ../gc/go.h\
- ../5l/5.out.h\
- gg.h\
- opt.h\
-
-OFILES=\
- ../5l/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/5g/cgen.c b/src/cmd/5g/cgen.c
index 6e2fbe20f..cccef94c9 100644
--- a/src/cmd/5g/cgen.c
+++ b/src/cmd/5g/cgen.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"
/*
@@ -62,6 +64,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
@@ -211,11 +216,11 @@ cgen(Node *n, Node *res)
goto ret;
case OMINUS:
+ regalloc(&n1, nl->type, N);
+ cgen(nl, &n1);
nodconst(&n3, nl->type, 0);
regalloc(&n2, nl->type, res);
- regalloc(&n1, nl->type, N);
gmove(&n3, &n2);
- cgen(nl, &n1);
gins(optoas(OSUB, nl->type), &n1, &n2);
gmove(&n2, res);
regfree(&n1);
@@ -278,6 +283,20 @@ cgen(Node *n, Node *res)
regfree(&n1);
break;
+ case OITAB:
+ // itable of interface value
+ igen(nl, &n1, res);
+ n1.op = OREGISTER; // was OINDREG
+ regalloc(&n2, n->type, &n1);
+ n1.op = OINDREG;
+ n1.type = n->type;
+ n1.xoffset = 0;
+ gmove(&n1, &n2);
+ gmove(&n2, res);
+ regfree(&n1);
+ regfree(&n2);
+ break;
+
case OLEN:
if(istype(nl->type, TMAP) || istype(nl->type, TCHAN)) {
// map has len in the first 32-bit word.
@@ -400,9 +419,9 @@ abop: // asymmetric binary
regalloc(&n2, nr->type, N);
cgen(nr, &n2);
} else {
- regalloc(&n2, nr->type, N);
+ regalloc(&n2, nr->type, res);
cgen(nr, &n2);
- regalloc(&n1, nl->type, res);
+ regalloc(&n1, nl->type, N);
cgen(nl, &n1);
}
gins(a, &n2, &n1);
@@ -848,8 +867,10 @@ bgen(Node *n, int true, Prog *to)
int et, a;
Node *nl, *nr, *r;
Node n1, n2, n3, n4, tmp;
+ NodeList *ll;
Prog *p1, *p2;
+ USED(n4); // in unreachable code below
if(debug['g']) {
dump("\nbgen", n);
}
@@ -860,9 +881,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)
@@ -875,7 +893,6 @@ bgen(Node *n, int true, Prog *to)
patch(gins(AEND, N, N), to);
goto ret;
}
- nl = N;
nr = N;
switch(n->op) {
@@ -951,7 +968,10 @@ bgen(Node *n, int true, Prog *to)
p1 = gbranch(AB, T);
p2 = gbranch(AB, T);
patch(p1, pc);
+ ll = n->ninit;
+ n->ninit = nil;
bgen(n, 1, p2);
+ n->ninit = ll;
patch(gbranch(AB, T), to);
patch(p2, pc);
goto ret;
@@ -984,6 +1004,7 @@ bgen(Node *n, int true, Prog *to)
regfree(&n1);
break;
+#ifdef NOTDEF
a = optoas(a, types[tptr]);
regalloc(&n1, types[tptr], N);
regalloc(&n3, types[tptr], N);
@@ -1001,6 +1022,7 @@ bgen(Node *n, int true, Prog *to)
regfree(&n3);
regfree(&n1);
break;
+#endif
}
if(isinter(nl->type)) {
@@ -1019,6 +1041,7 @@ bgen(Node *n, int true, Prog *to)
regfree(&n1);
break;
+#ifdef NOTDEF
a = optoas(a, types[tptr]);
regalloc(&n1, types[tptr], N);
regalloc(&n3, types[tptr], N);
@@ -1036,6 +1059,7 @@ bgen(Node *n, int true, Prog *to)
regfree(&n3);
regfree(&n4);
break;
+#endif
}
if(iscomplex[nl->type->etype]) {
@@ -1059,7 +1083,7 @@ bgen(Node *n, int true, Prog *to)
}
if(nr->op == OLITERAL) {
- if(nr->val.ctype == CTINT && mpgetfix(nr->val.u.xval) == 0) {
+ if(isconst(nr, CTINT) && mpgetfix(nr->val.u.xval) == 0) {
gencmp0(nl, nl->type, a, to);
break;
}
@@ -1186,7 +1210,7 @@ stkof(Node *n)
* NB: character copy assumed little endian architecture
*/
void
-sgen(Node *n, Node *res, int32 w)
+sgen(Node *n, Node *res, int64 w)
{
Node dst, src, tmp, nend;
int32 c, odst, osrc;
@@ -1194,25 +1218,34 @@ sgen(Node *n, Node *res, int32 w)
Prog *p, *ploop;
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(w < 0)
- fatal("sgen copy %d", w);
+
if(n->ullman >= UINF && res->ullman >= UINF)
fatal("sgen UINF");
+
+ if(w < 0 || (int32)w != w)
+ fatal("sgen copy %lld", w);
+
if(n->type == T)
fatal("sgen: missing type");
+ if(w == 0) {
+ // evaluate side effects only.
+ regalloc(&dst, types[tptr], N);
+ agen(res, &dst);
+ agen(n, &dst);
+ regfree(&dst);
+ return;
+ }
+
// determine alignment.
// want to avoid unaligned access, so have to use
// smaller operations for less aligned types.
// for example moving [4]byte must use 4 MOVB not 1 MOVW.
align = n->type->align;
- op = 0;
switch(align) {
default:
fatal("sgen: invalid alignment %d for %T", align, n->type);
@@ -1227,7 +1260,7 @@ sgen(Node *n, Node *res, int32 w)
break;
}
if(w%align)
- fatal("sgen: unaligned size %d (align=%d) for %T", w, align, n->type);
+ fatal("sgen: unaligned size %lld (align=%d) for %T", w, align, n->type);
c = w / align;
// offset on the stack
@@ -1313,7 +1346,6 @@ sgen(Node *n, Node *res, int32 w)
p->from.type = D_OREG;
p->from.offset = dir;
p->scond |= C_PBIT;
- ploop = p;
p = gins(op, &tmp, &dst);
p->to.type = D_OREG;
diff --git a/src/cmd/5g/cgen64.c b/src/cmd/5g/cgen64.c
index b56df765b..1235d1ace 100644
--- a/src/cmd/5g/cgen64.c
+++ b/src/cmd/5g/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"
/*
@@ -240,7 +242,7 @@ cgen64(Node *n, Node *res)
// shift is >= 1<<32
split64(r, &cl, &ch);
gmove(&ch, &s);
- p1 = gins(ATST, &s, N);
+ gins(ATST, &s, N);
p6 = gbranch(ABNE, T);
gmove(&cl, &s);
splitclean();
@@ -248,7 +250,7 @@ cgen64(Node *n, Node *res)
gmove(r, &s);
p6 = P;
}
- p1 = gins(ATST, &s, N);
+ gins(ATST, &s, N);
// shift == 0
p1 = gins(AMOVW, &bl, &al);
@@ -411,7 +413,7 @@ olsh_break:
gmove(r, &s);
p6 = P;
}
- p1 = gins(ATST, &s, N);
+ gins(ATST, &s, N);
// shift == 0
p1 = gins(AMOVW, &bl, &al);
@@ -453,9 +455,9 @@ olsh_break:
p1 = gins(AMOVW, &bh, &al);
p1->scond = C_SCOND_EQ;
if(bh.type->etype == TINT32)
- p1 = gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
+ gshift(AMOVW, &bh, SHIFT_AR, 31, &ah);
else
- p1 = gins(AEOR, &ah, &ah);
+ gins(AEOR, &ah, &ah);
p4 = gbranch(ABEQ, T);
// check if shift is < 64
diff --git a/src/cmd/5g/doc.go b/src/cmd/5g/doc.go
index e86013bdd..5a4a772fb 100644
--- a/src/cmd/5g/doc.go
+++ b/src/cmd/5g/doc.go
@@ -9,7 +9,5 @@ The $GOARCH for these tools is arm.
It reads .go files and outputs .5 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/5g/galign.c b/src/cmd/5g/galign.c
index 12766102f..070804217 100644
--- a/src/cmd/5g/galign.c
+++ b/src/cmd/5g/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 = '5';
diff --git a/src/cmd/5g/gg.h b/src/cmd/5g/gg.h
index ce4558e21..7dbf3beec 100644
--- a/src/cmd/5g/gg.h
+++ b/src/cmd/5g/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>
+#ifndef EXTERN
+#define EXTERN extern
+#endif
#include "../gc/go.h"
#include "../5l/5.out.h"
-#ifndef EXTERN
-#define EXTERN extern
-#endif
-
typedef struct Addr Addr;
struct Addr
@@ -46,27 +43,26 @@ struct Prog
uchar scond;
};
+#define TEXTFLAG reg
+
#define REGALLOC_R0 0
#define REGALLOC_RMAX REGEXT
#define REGALLOC_F0 (REGALLOC_RMAX+1)
#define REGALLOC_FMAX (REGALLOC_F0 + FREGEXT)
-EXTERN Biobuf* bout;
EXTERN int32 dynloc;
EXTERN uchar reg[REGALLOC_FMAX+1];
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;
EXTERN Node* panicindex;
EXTERN Node* panicslice;
EXTERN Node* throwreturn;
-EXTERN long unmappedzero;
+extern long unmappedzero;
EXTERN int maxstksize;
/*
@@ -98,7 +94,7 @@ void igen(Node*, Node*, Node*);
void agenr(Node *n, Node *a, Node *res);
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*);
@@ -169,3 +165,6 @@ int Yconv(Fmt*);
void listinit(void);
void zaddr(Biobuf*, Addr*, int);
+
+#pragma varargck type "D" Addr*
+#pragma varargck type "M" Addr*
diff --git a/src/cmd/5g/ggen.c b/src/cmd/5g/ggen.c
index 3f5f47e7b..de100620b 100644
--- a/src/cmd/5g/ggen.c
+++ b/src/cmd/5g/ggen.c
@@ -4,6 +4,8 @@
#undef EXTERN
#define EXTERN
+#include <u.h>
+#include <libc.h>
#include "gg.h"
#include "opt.h"
@@ -12,7 +14,6 @@ defframe(Prog *ptxt)
{
// fill in argument size
ptxt->to.type = D_CONST2;
- ptxt->reg = 0; // flags
ptxt->to.offset2 = rnd(curfn->type->argwid, widthptr);
// fill in final stack size
@@ -28,10 +29,10 @@ markautoused(Prog* p)
{
for (; p; p = p->link) {
if (p->from.name == D_AUTO && p->from.node)
- p->from.node->used++;
+ p->from.node->used = 1;
if (p->to.name == D_AUTO && p->to.node)
- p->to.node->used++;
+ p->to.node->used = 1;
}
}
@@ -544,7 +545,7 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
}
// test for shift being 0
- p1 = gins(ATST, &n1, N);
+ gins(ATST, &n1, N);
p3 = gbranch(ABEQ, T);
// test and fix up large shifts
diff --git a/src/cmd/5g/gobj.c b/src/cmd/5g/gobj.c
index 27c8be67d..b562ba888 100644
--- a/src/cmd/5g/gobj.c
+++ b/src/cmd/5g/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
@@ -266,54 +268,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 *sym, int off, char *t, int n)
{
@@ -353,6 +307,7 @@ datastring(char *s, int len, Addr *a)
a->offset = widthptr+4; // skip header
a->reg = NREG;
a->sym = sym;
+ a->node = sym->def;
}
/*
@@ -371,6 +326,7 @@ datagostring(Strlit *sval, Addr *a)
a->offset = 0; // header
a->reg = NREG;
a->sym = sym;
+ a->node = sym->def;
}
void
@@ -379,6 +335,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));
diff --git a/src/cmd/5g/gsubr.c b/src/cmd/5g/gsubr.c
index ddaf52a88..9acf93670 100644
--- a/src/cmd/5g/gsubr.c
+++ b/src/cmd/5g/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(kaib): Can make this bigger if we move
@@ -50,6 +52,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.
@@ -59,10 +65,23 @@ 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;
+ p->reg = 0; // used for flags
+ } else {
+ p = pc;
+ pc = mal(sizeof(*pc));
+ clearp(pc);
+ p->link = pc;
+ }
if(lineno == 0) {
if(debug['K'])
@@ -71,10 +90,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.
@@ -84,6 +114,8 @@ gbranch(int as, Type *t)
{
Prog *p;
+ USED(t);
+
p = prog(as);
p->to.type = D_BRANCH;
p->to.branch = P;
@@ -222,6 +254,10 @@ ggloblnod(Node *nam, int32 width)
p->to.sym = S;
p->to.type = D_CONST;
p->to.offset = width;
+ if(nam->readonly)
+ p->reg = RODATA;
+ if(nam->type != T && !haspointers(nam->type))
+ p->reg |= NOPTR;
}
void
@@ -238,6 +274,7 @@ ggloblsym(Sym *s, int32 width, int dupok)
p->to.offset = width;
if(dupok)
p->reg = DUPOK;
+ p->reg |= RODATA;
}
int
@@ -315,6 +352,8 @@ anyregalloc(void)
return 0;
}
+uintptr regpc[REGALLOC_FMAX+1];
+
/*
* allocate register of type t, leave in n.
* if o != N, o is desired fixed register.
@@ -325,7 +364,7 @@ regalloc(Node *n, Type *t, Node *o)
{
int i, et, fixfree, floatfree;
- if(debug['r']) {
+ if(0 && debug['r']) {
fixfree = 0;
for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++)
if(reg[i] == 0)
@@ -358,9 +397,12 @@ regalloc(Node *n, Type *t, Node *o)
goto out;
}
for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++)
- if(reg[i] == 0)
+ if(reg[i] == 0) {
+ regpc[i] = (uintptr)getcallerpc(&n);
goto out;
-
+ }
+ for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++)
+ print("%d %p\n", i, regpc[i]);
yyerror("out of fixed registers");
goto err;
@@ -398,7 +440,7 @@ regfree(Node *n)
{
int i, fixfree, floatfree;
- if(debug['r']) {
+ if(0 && debug['r']) {
fixfree = 0;
for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++)
if(reg[i] == 0)
@@ -415,11 +457,13 @@ regfree(Node *n)
if(n->op != OREGISTER && n->op != OINDREG)
fatal("regfree: not a register");
i = n->val.u.reg;
- if(i < 0 || i >= sizeof(reg))
+ if(i < 0 || i >= nelem(reg) || i >= nelem(regpc))
fatal("regfree: reg out of range");
if(reg[i] <= 0)
fatal("regfree: reg not allocated");
reg[i]--;
+ if(reg[i] == 0)
+ regpc[i] = 0;
}
/*
@@ -481,8 +525,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;
fp:
+ // Rewrite argument named _ to __,
+ // or else the assignment to _ will be
+ // discarded during code generation.
+ if(isblank(n))
+ n->sym = lookup("__");
+
switch(fp) {
default:
fatal("nodarg %T %d", t, fp);
@@ -1066,7 +1117,8 @@ gins(int as, Node *f, Node *t)
if(f != N)
naddr(f, &af, 1);
if(t != N)
- naddr(t, &at, 1); p = prog(as);
+ naddr(t, &at, 1);
+ p = prog(as);
if(f != N)
p->from = af;
if(t != N)
@@ -1232,6 +1284,7 @@ naddr(Node *n, Addr *a, int canemitcode)
a->sym = n->left->sym;
a->type = D_OREG;
a->name = D_PARAM;
+ a->node = n->left->orig;
break;
case ONAME:
@@ -1242,9 +1295,11 @@ naddr(Node *n, Addr *a, int canemitcode)
a->etype = simtype[n->type->etype];
a->width = n->type->width;
}
- 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) {
@@ -1263,8 +1318,6 @@ naddr(Node *n, Addr *a, int canemitcode)
break;
case PAUTO:
a->name = D_AUTO;
- if (n->sym)
- a->node = n->orig;
break;
case PPARAM:
case PPARAMOUT:
@@ -1287,6 +1340,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);
@@ -1307,6 +1361,16 @@ naddr(Node *n, Addr *a, int canemitcode)
}
break;
+ case OITAB:
+ // itable of interface value
+ naddr(n->left, a, canemitcode);
+ a->etype = TINT32;
+ if(a->type == D_CONST && a->offset == 0)
+ break; // len(nil)
+ if(a->offset >= unmappedzero && a->offset-Array_nel < unmappedzero)
+ checkoffset(a, canemitcode);
+ break;
+
case OLEN:
// len of string or slice
naddr(n->left, a, canemitcode);
@@ -1744,7 +1808,7 @@ sudoaddable(int as, Node *n, Addr *a, int *w)
switch(n->op) {
case OLITERAL:
- if(n->val.ctype != CTINT)
+ if(!isconst(n, CTINT))
break;
v = mpgetfix(n->val.u.xval);
if(v >= 32000 || v <= -32000)
diff --git a/src/cmd/5g/list.c b/src/cmd/5g/list.c
index 0c6dbbf71..9bc3a9a9a 100644
--- a/src/cmd/5g/list.c
+++ b/src/cmd/5g/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"
// TODO(kaib): make 5g/list.c congruent with 5l/list.c
@@ -57,7 +59,7 @@ Pconv(Fmt *fp)
switch(p->as) {
default:
snprint(str1, sizeof(str1), "%A%C", p->as, p->scond);
- if(p->reg == NREG)
+ if(p->reg == NREG && p->as != AGLOBL)
snprint(str, sizeof(str), "%.4d (%L) %-7s %D,%D",
p->loc, p->lineno, str1, &p->from, &p->to);
else
diff --git a/src/cmd/5g/peep.c b/src/cmd/5g/peep.c
index 6cc93db12..e87f5d697 100644
--- a/src/cmd/5g/peep.c
+++ b/src/cmd/5g/peep.c
@@ -29,6 +29,8 @@
// THE SOFTWARE.
+#include <u.h>
+#include <libc.h>
#include "gg.h"
#include "opt.h"
@@ -45,6 +47,9 @@ peep(void)
Reg *r, *r1, *r2;
Prog *p, *p1;
int t;
+
+ p1 = nil;
+ USED(p1); // ... in unreachable code...
/*
* complete R structure
*/
@@ -115,12 +120,14 @@ loop1:
}
break;
+#ifdef NOTDEF
if(p->scond == C_SCOND_NONE)
if(regtyp(&p->to))
if(isdconst(&p->from)) {
constprop(&p->from, &p->to, r->s1);
}
break;
+#endif
}
}
if(t)
@@ -128,6 +135,7 @@ loop1:
return;
+#ifdef NOTDEF
for(r=firstr; r!=R; r=r->link) {
p = r->prog;
switch(p->as) {
@@ -255,6 +263,7 @@ return;
// }
predicate();
+#endif
}
Reg*
@@ -1159,7 +1168,6 @@ copyu(Prog *p, Adr *v, Adr *s)
return 3;
return 0;
}
- return 0;
}
/*
diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c
index 2d2a6d01a..93724d032 100644
--- a/src/cmd/5g/reg.c
+++ b/src/cmd/5g/reg.c
@@ -29,6 +29,8 @@
// THE SOFTWARE.
+#include <u.h>
+#include <libc.h>
#include "gg.h"
#include "opt.h"
@@ -40,6 +42,9 @@
int noreturn(Prog *p);
static int first = 0;
+static void fixjmp(Prog*);
+
+
Reg*
rega(void)
{
@@ -90,8 +95,8 @@ setoutvar(void)
ovar.b[z] |= bit.b[z];
t = structnext(&save);
}
-//if(bany(b))
-//print("ovars = %Q\n", &ovar);
+//if(bany(ovar))
+//print("ovar = %Q\n", ovar);
}
void
@@ -112,19 +117,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;
}
}
@@ -169,6 +174,8 @@ regopt(Prog *firstp)
if(first == 0) {
fmtinstall('Q', Qconv);
}
+
+ fixjmp(firstp);
first++;
if(debug['K']) {
@@ -202,7 +209,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(REGSP)|RtoB(REGLINK)|RtoB(REGPC);
for(z=0; z<BITS; z++) {
@@ -750,9 +757,9 @@ addmove(Reg *r, int bn, int rn, int f)
v = var + bn;
a = &p1->to;
- a->sym = v->sym;
a->name = v->name;
a->node = v->node;
+ a->sym = v->node->sym;
a->offset = v->offset;
a->etype = v->etype;
a->type = D_OREG;
@@ -838,11 +845,10 @@ mkvar(Reg *r, Adr *a)
int i, t, n, et, z, w, flag;
int32 o;
Bits bit;
- Sym *s;
+ Node *node;
// mark registers used
t = a->type;
- n = D_NONE;
flag = 0;
switch(t) {
@@ -909,10 +915,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;
@@ -920,7 +929,7 @@ mkvar(Reg *r, Adr *a)
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)
@@ -944,7 +953,7 @@ mkvar(Reg *r, Adr *a)
}
if(nvar >= NVAR) {
- if(debug['w'] > 1 && s)
+ if(debug['w'] > 1 && node)
fatal("variable not optimized: %D", a);
goto none;
}
@@ -953,17 +962,16 @@ mkvar(Reg *r, Adr *a)
nvar++;
//print("var %d %E %D %S\n", i, et, a, s);
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);
bit = blsh(i);
if(n == D_EXTERN || n == D_STATIC)
@@ -1021,6 +1029,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]) |
@@ -1156,10 +1171,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;
}
@@ -1570,7 +1587,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))
@@ -1605,3 +1622,123 @@ dumpit(char *str, Reg *r0)
// }
}
}
+
+/*
+ * the code generator depends on being able to write out JMP (B)
+ * 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 == AB && 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->regp != dead)
+ break;
+ p->regp = alive;
+ if(p->as != ABL && p->to.type == D_BRANCH && p->to.branch)
+ mark(p->to.branch);
+ if(p->as == AB || p->as == ARET || (p->as == ABL && 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 B, 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 != ABL && p->to.type == D_BRANCH && p->to.branch && p->to.branch->as == AB) {
+ p->to.branch = chasejmp(p->to.branch, &jmploop);
+ if(debug['R'] && debug['v'])
+ print("->%P\n", p);
+ }
+ p->regp = 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->regp == 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 == AB && 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");
+ }
+}