summaryrefslogtreecommitdiff
path: root/src/cmd/5g
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2011-06-30 15:34:22 +0200
committerOndřej Surý <ondrej@sury.org>2011-06-30 15:34:22 +0200
commitd39f5aa373a4422f7a5f3ee764fb0f6b0b719d61 (patch)
tree1833f8b72a4b3a8f00d0d143b079a8fcad01c6ae /src/cmd/5g
parent8652e6c371b8905498d3d314491d36c58d5f68d5 (diff)
downloadgolang-upstream/58.tar.gz
Imported Upstream version 58upstream/58
Diffstat (limited to 'src/cmd/5g')
-rw-r--r--src/cmd/5g/Makefile13
-rw-r--r--src/cmd/5g/cgen.c217
-rw-r--r--src/cmd/5g/gg.h5
-rw-r--r--src/cmd/5g/ggen.c110
-rw-r--r--src/cmd/5g/gsubr.c3
-rw-r--r--src/cmd/5g/reg.c184
6 files changed, 271 insertions, 261 deletions
diff --git a/src/cmd/5g/Makefile b/src/cmd/5g/Makefile
index 6873fbc68..b47014a4e 100644
--- a/src/cmd/5g/Makefile
+++ b/src/cmd/5g/Makefile
@@ -15,16 +15,17 @@ HFILES=\
OFILES=\
../5l/enam.$O\
- list.$O\
- galign.$O\
- gobj.$O\
- ggen.$O\
- gsubr.$O\
cgen.$O\
cgen64.$O\
cplx.$O\
- reg.$O\
+ galign.$O\
+ ggen.$O\
+ gobj.$O\
+ gsubr.$O\
+ list.$O\
peep.$O\
+ pgen.$O\
+ reg.$O\
LIB=\
../gc/gc.a\
diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c
index 4e5f7ebcd..76e2707fa 100644
--- a/src/cmd/5g/cgen.c
+++ b/src/cmd/5g/cgen.c
@@ -1190,7 +1190,8 @@ void
sgen(Node *n, Node *res, int32 w)
{
Node dst, src, tmp, nend;
- int32 c, q, odst, osrc;
+ int32 c, odst, osrc;
+ int dir, align, op;
Prog *p, *ploop;
if(debug['g']) {
@@ -1200,17 +1201,39 @@ sgen(Node *n, Node *res, int32 w)
}
if(w == 0)
return;
- if(n->ullman >= UINF && res->ullman >= UINF) {
- fatal("sgen UINF");
- }
-
if(w < 0)
fatal("sgen copy %d", w);
+ if(n->ullman >= UINF && res->ullman >= UINF)
+ fatal("sgen UINF");
+ if(n->type == T)
+ fatal("sgen: missing type");
+
+ // 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);
+ case 1:
+ op = AMOVB;
+ break;
+ case 2:
+ op = AMOVH;
+ break;
+ case 4:
+ op = AMOVW;
+ break;
+ }
+ if(w%align)
+ fatal("sgen: unaligned size %d (align=%d) for %T", w, align, n->type);
+ c = w / align;
// offset on the stack
osrc = stkof(n);
odst = stkof(res);
-
if(osrc != -1000 && odst != -1000 && (osrc == 1000 || odst == 1000)) {
// osrc and odst both on stack, and at least one is in
// an unknown position. Could generate code to test
@@ -1221,12 +1244,15 @@ sgen(Node *n, Node *res, int32 w)
sgen(&tmp, res, w);
return;
}
-
- if(osrc % 4 != 0 || odst %4 != 0)
- fatal("sgen: non word(4) aligned offset src %d or dst %d", osrc, odst);
+ if(osrc%align != 0 || odst%align != 0)
+ fatal("sgen: unaligned offset src %d or dst %d (align %d)", osrc, odst, align);
+ // if we are copying forward on the stack and
+ // the src and dst overlap, then reverse direction
+ dir = align;
+ if(osrc < odst && odst < osrc+w)
+ dir = -dir;
regalloc(&dst, types[tptr], res);
-
if(n->ullman >= res->ullman) {
agen(n, &dst); // temporarily use dst
regalloc(&src, types[tptr], N);
@@ -1240,141 +1266,64 @@ sgen(Node *n, Node *res, int32 w)
regalloc(&tmp, types[TUINT32], N);
- c = w % 4; // bytes
- q = w / 4; // quads
-
- // if we are copying forward on the stack and
- // the src and dst overlap, then reverse direction
- if(osrc < odst && odst < osrc+w) {
- if(c != 0)
- fatal("sgen: reverse character copy not implemented");
- if(q >= 4) {
- regalloc(&nend, types[TUINT32], N);
- // set up end marker to 4 bytes before source
- p = gins(AMOVW, &src, &nend);
- p->from.type = D_CONST;
- p->from.offset = -4;
-
- // move src and dest to the end of block
- p = gins(AMOVW, &src, &src);
- p->from.type = D_CONST;
- p->from.offset = (q-1)*4;
-
- p = gins(AMOVW, &dst, &dst);
- p->from.type = D_CONST;
- p->from.offset = (q-1)*4;
-
- p = gins(AMOVW, &src, &tmp);
- p->from.type = D_OREG;
- p->from.offset = -4;
- p->scond |= C_PBIT;
- ploop = p;
+ // set up end marker
+ memset(&nend, 0, sizeof nend);
+ if(c >= 4) {
+ regalloc(&nend, types[TUINT32], N);
- p = gins(AMOVW, &tmp, &dst);
- p->to.type = D_OREG;
- p->to.offset = -4;
- p->scond |= C_PBIT;
-
- p = gins(ACMP, &src, N);
- raddr(&nend, p);
+ p = gins(AMOVW, &src, &nend);
+ p->from.type = D_CONST;
+ if(dir < 0)
+ p->from.offset = dir;
+ else
+ p->from.offset = w;
+ }
- patch(gbranch(ABNE, T), ploop);
+ // move src and dest to the end of block if necessary
+ if(dir < 0) {
+ p = gins(AMOVW, &src, &src);
+ p->from.type = D_CONST;
+ p->from.offset = w + dir;
- regfree(&nend);
- } else {
- // move src and dest to the end of block
- p = gins(AMOVW, &src, &src);
- p->from.type = D_CONST;
- p->from.offset = (q-1)*4;
-
- p = gins(AMOVW, &dst, &dst);
- p->from.type = D_CONST;
- p->from.offset = (q-1)*4;
-
- while(q > 0) {
- p = gins(AMOVW, &src, &tmp);
- p->from.type = D_OREG;
- p->from.offset = -4;
- p->scond |= C_PBIT;
-
- p = gins(AMOVW, &tmp, &dst);
- p->to.type = D_OREG;
- p->to.offset = -4;
- p->scond |= C_PBIT;
-
- q--;
- }
- }
+ p = gins(AMOVW, &dst, &dst);
+ p->from.type = D_CONST;
+ p->from.offset = w + dir;
+ }
+
+ // move
+ if(c >= 4) {
+ p = gins(op, &src, &tmp);
+ 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;
+ p->to.offset = dir;
+ p->scond |= C_PBIT;
+
+ p = gins(ACMP, &src, N);
+ raddr(&nend, p);
+
+ patch(gbranch(ABNE, T), ploop);
+ regfree(&nend);
} else {
- // normal direction
- if(q >= 4) {
- regalloc(&nend, types[TUINT32], N);
- p = gins(AMOVW, &src, &nend);
- p->from.type = D_CONST;
- p->from.offset = q*4;
-
- p = gins(AMOVW, &src, &tmp);
+ while(c-- > 0) {
+ p = gins(op, &src, &tmp);
p->from.type = D_OREG;
- p->from.offset = 4;
+ p->from.offset = dir;
p->scond |= C_PBIT;
ploop = p;
-
- p = gins(AMOVW, &tmp, &dst);
+
+ p = gins(op, &tmp, &dst);
p->to.type = D_OREG;
- p->to.offset = 4;
+ p->to.offset = dir;
p->scond |= C_PBIT;
-
- p = gins(ACMP, &src, N);
- raddr(&nend, p);
-
- patch(gbranch(ABNE, T), ploop);
-
- regfree(&nend);
- } else
- while(q > 0) {
- p = gins(AMOVW, &src, &tmp);
- p->from.type = D_OREG;
- p->from.offset = 4;
- p->scond |= C_PBIT;
-
- p = gins(AMOVW, &tmp, &dst);
- p->to.type = D_OREG;
- p->to.offset = 4;
- p->scond |= C_PBIT;
-
- q--;
- }
-
- if (c != 0) {
- // MOVW (src), tmp
- p = gins(AMOVW, &src, &tmp);
- p->from.type = D_OREG;
-
- // MOVW tmp<<((4-c)*8),src
- gshift(AMOVW, &tmp, SHIFT_LL, ((4-c)*8), &src);
-
- // MOVW src>>((4-c)*8),src
- gshift(AMOVW, &src, SHIFT_LR, ((4-c)*8), &src);
-
- // MOVW (dst), tmp
- p = gins(AMOVW, &dst, &tmp);
- p->from.type = D_OREG;
-
- // MOVW tmp>>(c*8),tmp
- gshift(AMOVW, &tmp, SHIFT_LR, (c*8), &tmp);
-
- // MOVW tmp<<(c*8),tmp
- gshift(AMOVW, &tmp, SHIFT_LL, c*8, &tmp);
-
- // ORR src, tmp
- gins(AORR, &src, &tmp);
-
- // MOVW tmp, (dst)
- p = gins(AMOVW, &tmp, &dst);
- p->to.type = D_OREG;
}
}
- regfree(&dst);
+
+ regfree(&dst);
regfree(&src);
regfree(&tmp);
}
diff --git a/src/cmd/5g/gg.h b/src/cmd/5g/gg.h
index 78e6833b2..ce4558e21 100644
--- a/src/cmd/5g/gg.h
+++ b/src/cmd/5g/gg.h
@@ -23,10 +23,11 @@ struct Addr
char sval[NSNAME];
Sym* sym;
+ Node* node;
int width;
uchar type;
char name;
- char reg;
+ uchar reg;
char pun;
uchar etype;
};
@@ -41,7 +42,7 @@ struct Prog
Addr to; // dst address
Prog* link; // next instruction in this func
void* regp; // points to enclosing Reg struct
- char reg; // doubles as width in DATA op
+ uchar reg; // doubles as width in DATA op
uchar scond;
};
diff --git a/src/cmd/5g/ggen.c b/src/cmd/5g/ggen.c
index 7197709d4..0bc1b38fc 100644
--- a/src/cmd/5g/ggen.c
+++ b/src/cmd/5g/ggen.c
@@ -7,107 +7,9 @@
#include "gg.h"
#include "opt.h"
-static Prog *pret;
-
void
-compile(Node *fn)
+defframe(Prog *ptxt)
{
- Plist *pl;
- Node nod1;
- Prog *ptxt;
- int32 lno;
- Type *t;
- Iter save;
-
- if(newproc == N) {
- newproc = sysfunc("newproc");
- deferproc = sysfunc("deferproc");
- deferreturn = sysfunc("deferreturn");
- panicindex = sysfunc("panicindex");
- panicslice = sysfunc("panicslice");
- throwreturn = sysfunc("throwreturn");
- }
-
- if(fn->nbody == nil)
- return;
-
- // set up domain for labels
- clearlabels();
-
- lno = setlineno(fn);
-
- curfn = fn;
- dowidth(curfn->type);
-
- if(curfn->type->outnamed) {
- // add clearing of the output parameters
- t = structfirst(&save, getoutarg(curfn->type));
- while(t != T) {
- if(t->nname != N)
- curfn->nbody = concat(list1(nod(OAS, t->nname, N)), curfn->nbody);
- t = structnext(&save);
- }
- }
-
- hasdefer = 0;
- walk(curfn);
- if(nerrors != 0 || isblank(curfn->nname))
- goto ret;
-
- allocparams();
-
- continpc = P;
- breakpc = P;
-
- pl = newplist();
- pl->name = curfn->nname;
-
- setlineno(curfn);
-
- nodconst(&nod1, types[TINT32], 0);
- ptxt = gins(ATEXT, curfn->nname, &nod1);
- afunclit(&ptxt->from);
-
- ginit();
- genlist(curfn->enter);
-
- pret = nil;
- if(hasdefer || curfn->exit) {
- Prog *p1;
-
- p1 = gjmp(nil);
- pret = gjmp(nil);
- patch(p1, pc);
- }
-
- genlist(curfn->nbody);
- gclean();
- checklabels();
- if(nerrors != 0)
- goto ret;
-
- if(curfn->type->outtuple != 0)
- ginscall(throwreturn, 0);
-
- if(pret)
- patch(pret, pc);
- ginit();
- if(hasdefer)
- ginscall(deferreturn, 0);
- if(curfn->exit)
- genlist(curfn->exit);
- gclean();
- if(nerrors != 0)
- goto ret;
- if(curfn->endlineno)
- lineno = curfn->endlineno;
- pc->as = ARET; // overwrite AEND
- pc->lineno = lineno;
-
- if(!debug['N'] || debug['R'] || debug['P']) {
- regopt(ptxt);
- }
-
// fill in argument size
ptxt->to.type = D_CONST2;
ptxt->reg = 0; // flags
@@ -118,12 +20,6 @@ compile(Node *fn)
maxstksize = stksize;
ptxt->to.offset = rnd(maxstksize+maxarg, widthptr);
maxstksize = 0;
-
- if(debug['f'])
- frame(0);
-
-ret:
- lineno = lno;
}
/*
@@ -197,7 +93,7 @@ ginscall(Node *f, int proc)
nodconst(&con, types[TINT32], 0);
p = gins(ACMP, &con, N);
p->reg = 0;
- patch(gbranch(ABNE, T), pret);
+ patch(gbranch(ABNE, T), retpc);
}
break;
}
@@ -401,7 +297,7 @@ cgen_ret(Node *n)
{
genlist(n->list); // copy out args
if(hasdefer || curfn->exit)
- gjmp(pret);
+ gjmp(retpc);
else
gins(ARET, N, N);
}
diff --git a/src/cmd/5g/gsubr.c b/src/cmd/5g/gsubr.c
index 57cb56a64..caaa3e246 100644
--- a/src/cmd/5g/gsubr.c
+++ b/src/cmd/5g/gsubr.c
@@ -1159,6 +1159,7 @@ naddr(Node *n, Addr *a, int canemitcode)
a->type = D_NONE;
a->name = D_NONE;
a->reg = NREG;
+ a->node = N;
if(n == N)
return;
@@ -1247,6 +1248,8 @@ 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:
diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c
index 1cbeb3e3d..5fba02c9e 100644
--- a/src/cmd/5g/reg.c
+++ b/src/cmd/5g/reg.c
@@ -32,6 +32,8 @@
#include "gg.h"
#include "opt.h"
+#define NREGVAR 24
+#define REGBITS ((uint32)0xffffff)
#define P2R(p) (Reg*)(p->reg)
void addsplits(void);
@@ -128,6 +130,33 @@ setaddrs(Bits bit)
}
}
+static char* regname[] = {
+ ".R0",
+ ".R1",
+ ".R2",
+ ".R3",
+ ".R4",
+ ".R5",
+ ".R6",
+ ".R7",
+ ".R8",
+ ".R9",
+ ".R10",
+ ".R11",
+ ".R12",
+ ".R13",
+ ".R14",
+ ".R15",
+ ".F0",
+ ".F1",
+ ".F2",
+ ".F3",
+ ".F4",
+ ".F5",
+ ".F6",
+ ".F7",
+};
+
void
regopt(Prog *firstp)
{
@@ -136,7 +165,7 @@ regopt(Prog *firstp)
int i, z, nr;
uint32 vreg;
Bits bit;
-
+
if(first == 0) {
fmtinstall('Q', Qconv);
}
@@ -164,7 +193,17 @@ regopt(Prog *firstp)
r1 = R;
firstr = R;
lastr = R;
- nvar = 0;
+
+ /*
+ * control flow is more complicated in generated go code
+ * than in generated c code. define pseudo-variables for
+ * registers, so we have complete register usage information.
+ */
+ nvar = NREGVAR;
+ memset(var, 0, NREGVAR*sizeof var[0]);
+ for(i=0; i<NREGVAR; i++)
+ var[i].sym = lookup(regname[i]);
+
regbits = RtoB(REGSP)|RtoB(REGLINK)|RtoB(REGPC);
for(z=0; z<BITS; z++) {
externs.b[z] = 0;
@@ -223,6 +262,16 @@ regopt(Prog *firstp)
bit = mkvar(r, &p->from);
for(z=0; z<BITS; z++)
r->use1.b[z] |= bit.b[z];
+
+ /*
+ * middle always read when present
+ */
+ if(p->reg != NREG) {
+ if(p->from.type != D_FREG)
+ r->use1.b[0] |= RtoB(p->reg);
+ else
+ r->use1.b[0] |= FtoB(p->reg);
+ }
/*
* right side depends on opcode
@@ -233,6 +282,67 @@ regopt(Prog *firstp)
default:
yyerror("reg: unknown op: %A", p->as);
break;
+
+ /*
+ * right side read
+ */
+ case ATST:
+ case ATEQ:
+ case ACMP:
+ case ACMN:
+ case ACMPD:
+ case ACMPF:
+ rightread:
+ for(z=0; z<BITS; z++)
+ r->use2.b[z] |= bit.b[z];
+ break;
+
+ /*
+ * right side read or read+write, depending on middle
+ * ADD x, z => z += x
+ * ADD x, y, z => z = x + y
+ */
+ case AADD:
+ case AAND:
+ case AEOR:
+ case ASUB:
+ case ARSB:
+ case AADC:
+ case ASBC:
+ case ARSC:
+ case AORR:
+ case ABIC:
+ case ASLL:
+ case ASRL:
+ case ASRA:
+ case AMUL:
+ case AMULU:
+ case ADIV:
+ case AMOD:
+ case AMODU:
+ case ADIVU:
+ if(p->reg != NREG)
+ goto rightread;
+ // fall through
+
+ /*
+ * right side read+write
+ */
+ case AADDF:
+ case AADDD:
+ case ASUBF:
+ case ASUBD:
+ case AMULF:
+ case AMULD:
+ case ADIVF:
+ case ADIVD:
+ case AMULAL:
+ case AMULALU:
+ for(z=0; z<BITS; z++) {
+ r->use2.b[z] |= bit.b[z];
+ r->set.b[z] |= bit.b[z];
+ }
+ break;
/*
* right side write
@@ -240,11 +350,22 @@ regopt(Prog *firstp)
case ANOP:
case AMOVB:
case AMOVBU:
+ case AMOVD:
+ case AMOVDF:
+ case AMOVDW:
+ case AMOVF:
+ case AMOVFW:
case AMOVH:
case AMOVHU:
case AMOVW:
- case AMOVF:
- case AMOVD:
+ case AMOVWD:
+ case AMOVWF:
+ case AMVN:
+ case AMULL:
+ case AMULLU:
+ if((p->scond & C_SCOND) != C_SCOND_NONE)
+ for(z=0; z<BITS; z++)
+ r->use2.b[z] |= bit.b[z];
for(z=0; z<BITS; z++)
r->set.b[z] |= bit.b[z];
break;
@@ -397,6 +518,24 @@ loop2:
}
/*
+ * pass 4.5
+ * move register pseudo-variables into regu.
+ */
+ for(r = firstr; r != R; r = r->link) {
+ r->regu = (r->refbehind.b[0] | r->set.b[0]) & REGBITS;
+
+ r->set.b[0] &= ~REGBITS;
+ r->use1.b[0] &= ~REGBITS;
+ r->use2.b[0] &= ~REGBITS;
+ r->refbehind.b[0] &= ~REGBITS;
+ r->refahead.b[0] &= ~REGBITS;
+ r->calbehind.b[0] &= ~REGBITS;
+ r->calahead.b[0] &= ~REGBITS;
+ r->regdiff.b[0] &= ~REGBITS;
+ r->act.b[0] &= ~REGBITS;
+ }
+
+ /*
* pass 5
* isolate regions
* calculate costs (paint1)
@@ -606,6 +745,7 @@ addmove(Reg *r, int bn, int rn, int f)
a = &p1->to;
a->sym = v->sym;
a->name = v->name;
+ a->node = v->node;
a->offset = v->offset;
a->etype = v->etype;
a->type = D_OREG;
@@ -715,21 +855,40 @@ mkvar(Reg *r, Adr *a)
goto onereg;
case D_REGREG:
+ bit = zbits;
if(a->offset != NREG)
- r->regu |= RtoB(a->offset);
- goto onereg;
+ bit.b[0] |= RtoB(a->offset);
+ if(a->reg != NREG)
+ bit.b[0] |= RtoB(a->reg);
+ return bit;
case D_REG:
case D_SHIFT:
- case D_OREG:
onereg:
- if(a->reg != NREG)
- r->regu |= RtoB(a->reg);
+ if(a->reg != NREG) {
+ bit = zbits;
+ bit.b[0] = RtoB(a->reg);
+ return bit;
+ }
+ break;
+
+ case D_OREG:
+ if(a->reg != NREG) {
+ if(a == &r->prog->from)
+ r->use1.b[0] |= RtoB(a->reg);
+ else
+ r->use2.b[0] |= RtoB(a->reg);
+ if(r->prog->scond & (C_PBIT|C_WBIT))
+ r->set.b[0] |= RtoB(a->reg);
+ }
break;
case D_FREG:
- if(a->reg != NREG)
- r->regu |= FtoB(a->reg);
+ if(a->reg != NREG) {
+ bit = zbits;
+ bit.b[0] = FtoB(a->reg);
+ return bit;
+ }
break;
}
@@ -795,7 +954,8 @@ mkvar(Reg *r, Adr *a)
v->etype = et;
v->width = w;
v->addr = flag; // funny punning
-
+ v->node = a->node;
+
if(debug['R'])
print("bit=%2d et=%E pun=%d %D\n", i, et, flag, a);