diff --git a/src/cmd/5g/cgen64.c b/src/cmd/5g/cgen64.c index 4da8db2ae2..b56df765ba 100644 --- a/src/cmd/5g/cgen64.c +++ b/src/cmd/5g/cgen64.c @@ -158,7 +158,7 @@ cgen64(Node *n, Node *res) gins(AMOVW, &hi2, &ch); gins(AMOVW, &lo2, &cl); - // bl * cl + // bl * cl -> ah al p1 = gins(AMULLU, N, N); p1->from.type = D_REG; p1->from.reg = bl.val.u.reg; @@ -168,7 +168,7 @@ cgen64(Node *n, Node *res) p1->to.offset = al.val.u.reg; //print("%P\n", p1); - // bl * ch + // bl * ch + ah -> ah p1 = gins(AMULA, N, N); p1->from.type = D_REG; p1->from.reg = bl.val.u.reg; @@ -178,7 +178,7 @@ cgen64(Node *n, Node *res) p1->to.offset = ah.val.u.reg; //print("%P\n", p1); - // bh * cl + // bh * cl + ah -> ah p1 = gins(AMULA, N, N); p1->from.type = D_REG; p1->from.reg = bh.val.u.reg; diff --git a/src/cmd/5g/ggen.c b/src/cmd/5g/ggen.c index d5b00b34d5..e2f0e6bc0a 100644 --- a/src/cmd/5g/ggen.c +++ b/src/cmd/5g/ggen.c @@ -470,9 +470,10 @@ samereg(Node *a, Node *b) void cgen_shift(int op, Node *nl, Node *nr, Node *res) { - Node n1, n2, n3, t; + Node n1, n2, n3, nt, t, lo, hi; int w; - Prog *p1, *p2, *p3; + Prog *p1, *p2, *p3, *pbig; + Type *tr; uvlong sc; if(nl->type->width > 4) @@ -504,16 +505,43 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res) return; } - if(nl->ullman >= nr->ullman) { - regalloc(&n2, nl->type, res); - cgen(nl, &n2); - regalloc(&n1, nr->type, N); - cgen(nr, &n1); + pbig = P; + tr = nr->type; + if(tr->width > 4) { + tempname(&nt, nr->type); + if(nl->ullman >= nr->ullman) { + regalloc(&n2, nl->type, res); + cgen(nl, &n2); + cgen(nr, &nt); + n1 = nt; + } else { + cgen(nr, &nt); + regalloc(&n2, nl->type, res); + cgen(nl, &n2); + } + split64(&nt, &lo, &hi); + regalloc(&n1, types[TUINT32], N); + regalloc(&n3, types[TUINT32], N); + gmove(&lo, &n1); + gmove(&hi, &n3); + gins(ATST, &n3, N); + nodconst(&t, types[TUINT32], w); + p1 = gins(AMOVW, &t, &n1); + p1->scond = C_SCOND_NE; + tr = types[TUINT32]; + regfree(&n3); } else { - regalloc(&n1, nr->type, N); - cgen(nr, &n1); - regalloc(&n2, nl->type, res); - cgen(nl, &n2); + if(nl->ullman >= nr->ullman) { + regalloc(&n2, nl->type, res); + cgen(nl, &n2); + regalloc(&n1, nr->type, N); + cgen(nr, &n1); + } else { + regalloc(&n1, nr->type, N); + cgen(nr, &n1); + regalloc(&n2, nl->type, res); + cgen(nl, &n2); + } } // test for shift being 0 @@ -521,7 +549,7 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res) p3 = gbranch(ABEQ, T); // test and fix up large shifts - regalloc(&n3, nr->type, N); + regalloc(&n3, tr, N); nodconst(&t, types[TUINT32], w); gmove(&t, &n3); gcmp(ACMP, &n1, &n3); diff --git a/src/cmd/5g/gsubr.c b/src/cmd/5g/gsubr.c index 2d92184613..ddaf52a882 100644 --- a/src/cmd/5g/gsubr.c +++ b/src/cmd/5g/gsubr.c @@ -497,6 +497,7 @@ fp: n->class = PPARAM; break; } + n->typecheck = 1; return n; } @@ -1173,6 +1174,7 @@ naddr(Node *n, Addr *a, int canemitcode) a->name = D_NONE; a->reg = NREG; a->node = N; + a->etype = 0; if(n == N) return; @@ -1308,6 +1310,7 @@ naddr(Node *n, Addr *a, int canemitcode) case OLEN: // len of string or slice naddr(n->left, a, canemitcode); + a->etype = TINT32; if(a->type == D_CONST && a->offset == 0) break; // len(nil) a->offset += Array_nel; @@ -1318,6 +1321,7 @@ naddr(Node *n, Addr *a, int canemitcode) case OCAP: // cap of string or slice naddr(n->left, a, canemitcode); + a->etype = TINT32; if(a->type == D_CONST && a->offset == 0) break; // cap(nil) a->offset += Array_cap; @@ -1327,6 +1331,7 @@ naddr(Node *n, Addr *a, int canemitcode) case OADDR: naddr(n->left, a, canemitcode); + a->etype = tptr; switch(a->type) { case D_OREG: a->type = D_CONST; @@ -1819,6 +1824,7 @@ odot: a->type = D_NONE; a->name = D_NONE; + n1.type = n->type; naddr(&n1, a, 1); goto yes; @@ -1946,7 +1952,6 @@ oindex: a->type = D_OREG; a->reg = reg->val.u.reg; a->offset = 0; - goto yes; oindex_const: diff --git a/src/cmd/5g/peep.c b/src/cmd/5g/peep.c index 6f36e12d42..6cc93db12c 100644 --- a/src/cmd/5g/peep.c +++ b/src/cmd/5g/peep.c @@ -933,7 +933,6 @@ xtramodes(Reg *r, Adr *a) int copyu(Prog *p, Adr *v, Adr *s) { - switch(p->as) { default: @@ -1011,6 +1010,8 @@ copyu(Prog *p, Adr *v, Adr *s) return 0; } if(copyas(&p->to, v)) { + if(p->scond != C_SCOND_NONE) + return 2; if(copyau(&p->from, v)) return 4; return 3; @@ -1069,6 +1070,8 @@ copyu(Prog *p, Adr *v, Adr *s) return 0; } if(copyas(&p->to, v)) { + if(p->scond != C_SCOND_NONE) + return 2; if(p->reg == NREG) p->reg = p->to.reg; if(copyau(&p->from, v)) diff --git a/src/cmd/5g/reg.c b/src/cmd/5g/reg.c index 7bb33b7c25..2d2a6d01af 100644 --- a/src/cmd/5g/reg.c +++ b/src/cmd/5g/reg.c @@ -336,6 +336,7 @@ regopt(Prog *firstp) case AMULD: case ADIVF: case ADIVD: + case AMULA: case AMULAL: case AMULALU: for(z=0; zetype, bn, v->sym); p1->as = AMOVBU; break; case TINT16: @@ -843,9 +845,6 @@ mkvar(Reg *r, Adr *a) n = D_NONE; flag = 0; - if(a->pun) - flag = 1; - switch(t) { default: print("type %d %d %D\n", t, a->name, a); @@ -928,7 +927,7 @@ mkvar(Reg *r, Adr *a) if(!flag) return blsh(i); - // if they overlaps, disable both + // if they overlap, disable both if(overlap(v->offset, v->width, o, w)) { v->addr = 1; flag = 1; @@ -952,6 +951,7 @@ mkvar(Reg *r, Adr *a) i = nvar; nvar++; +//print("var %d %E %D %S\n", i, et, a, s); v = var+i; v->sym = s; v->offset = o; @@ -963,7 +963,7 @@ mkvar(Reg *r, Adr *a) v->node = a->node; if(debug['R']) - print("bit=%2d et=%E pun=%d %D\n", i, et, flag, a); + print("bit=%2d et=%2d w=%d+%d %S %D flag=%d\n", i, et, o, w, s, a, v->addr); bit = blsh(i); if(n == D_EXTERN || n == D_STATIC) @@ -1453,10 +1453,6 @@ paint3(Reg *r, int bn, int32 rb, int rn) void addreg(Adr *a, int rn) { - - if(a->type == D_CONST) - fatal("addreg: cant do this %D %d\n", a, rn); - a->sym = 0; a->name = D_NONE; a->type = D_REG; @@ -1477,8 +1473,7 @@ addreg(Adr *a, int rn) int32 RtoB(int r) { - - if(r < 2 || r >= REGTMP-2) // excluded R9 and R10 for m and g + if(r >= REGTMP-2) // excluded R9 and R10 for m and g return 0; return 1L << r; } diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c index 211915f544..d0d6d0c96d 100644 --- a/src/cmd/6g/gsubr.c +++ b/src/cmd/6g/gsubr.c @@ -473,6 +473,7 @@ fatal("shouldnt be used"); n->xoffset += types[tptr]->width; break; } + n->typecheck = 1; return n; } @@ -987,7 +988,6 @@ gins(int as, Node *f, Node *t) if(debug['g']) print("%P\n", p); - w = 0; switch(as) { case AMOVB: diff --git a/src/cmd/8g/gg.h b/src/cmd/8g/gg.h index 7da60d7677..9f7a66a295 100644 --- a/src/cmd/8g/gg.h +++ b/src/cmd/8g/gg.h @@ -9,7 +9,7 @@ #include "../8l/8.out.h" #ifndef EXTERN -#define EXTERN extern +#define EXTERN extern #endif typedef struct Addr Addr; diff --git a/src/cmd/8g/ggen.c b/src/cmd/8g/ggen.c index eaf3c01cc2..108c493aa3 100644 --- a/src/cmd/8g/ggen.c +++ b/src/cmd/8g/ggen.c @@ -620,9 +620,9 @@ cgen_div(int op, Node *nl, Node *nr, Node *res) void cgen_shift(int op, Node *nl, Node *nr, Node *res) { - Node n1, n2, cx, oldcx; + Node n1, n2, nt, cx, oldcx, hi, lo; int a, w; - Prog *p1; + Prog *p1, *p2; uvlong sc; if(nl->type->width > 4) @@ -656,8 +656,13 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res) gmove(&cx, &oldcx); } - nodreg(&n1, types[TUINT32], D_CX); - regalloc(&n1, nr->type, &n1); // to hold the shift type in CX + if(nr->type->width > 4) { + tempname(&nt, nr->type); + n1 = nt; + } else { + nodreg(&n1, types[TUINT32], D_CX); + regalloc(&n1, nr->type, &n1); // to hold the shift type in CX + } if(samereg(&cx, res)) regalloc(&n2, nl->type, N); @@ -672,8 +677,21 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res) } // test and fix up large shifts - gins(optoas(OCMP, nr->type), &n1, ncon(w)); - p1 = gbranch(optoas(OLT, types[TUINT32]), T); + if(nr->type->width > 4) { + // delayed reg alloc + nodreg(&n1, types[TUINT32], D_CX); + regalloc(&n1, types[TUINT32], &n1); // to hold the shift type in CX + split64(&nt, &lo, &hi); + gmove(&lo, &n1); + gins(optoas(OCMP, types[TUINT32]), &hi, ncon(0)); + p2 = gbranch(optoas(ONE, types[TUINT32]), T); + gins(optoas(OCMP, types[TUINT32]), &n1, ncon(w)); + p1 = gbranch(optoas(OLT, types[TUINT32]), T); + patch(p2, pc); + } else { + gins(optoas(OCMP, nr->type), &n1, ncon(w)); + p1 = gbranch(optoas(OLT, types[TUINT32]), T); + } if(op == ORSH && issigned[nl->type->etype]) { gins(a, ncon(w-1), &n2); } else { diff --git a/src/cmd/8g/reg.c b/src/cmd/8g/reg.c index a4828c3a39..2b878f62a2 100644 --- a/src/cmd/8g/reg.c +++ b/src/cmd/8g/reg.c @@ -865,7 +865,7 @@ mkvar(Reg *r, Adr *a) if(v->width == w) return blsh(i); - // if they overlaps, disable both + // if they overlap, disable both if(overlap(v->offset, v->width, o, w)) { if(debug['R']) print("disable %s\n", v->sym->name); @@ -874,8 +874,6 @@ mkvar(Reg *r, Adr *a) } } } - if(a->pun) - flag = 1; switch(et) { case 0: @@ -902,7 +900,7 @@ mkvar(Reg *r, Adr *a) v->node = a->node; if(debug['R']) - print("bit=%2d et=%2d w=%d %S %D flag=%d\n", i, et, w, s, a, v->addr); + print("bit=%2d et=%2d w=%d+%d %S %D flag=%d\n", i, et, o, w, s, a, v->addr); ostats.nvar++; bit = blsh(i); diff --git a/src/cmd/gc/bits.c b/src/cmd/gc/bits.c index 1f2a776fd3..7188ac4111 100644 --- a/src/cmd/gc/bits.c +++ b/src/cmd/gc/bits.c @@ -150,8 +150,11 @@ Qconv(Fmt *fp) fmtprint(fp, " "); if(var[i].sym == S) fmtprint(fp, "$%lld", var[i].offset); - else + else { fmtprint(fp, var[i].sym->name); + if(var[i].offset != 0) + fmtprint(fp, "%+d", var[i].offset); + } bits.b[i/32] &= ~(1L << (i%32)); } return 0; diff --git a/test/fixedbugs/bug356.go b/test/fixedbugs/bug356.go new file mode 100644 index 0000000000..d21f0cfac6 --- /dev/null +++ b/test/fixedbugs/bug356.go @@ -0,0 +1,41 @@ +// $G $D/$F.go && $L $F.$A && ./$A.out || echo BUG: bug344 + +// Copyright 2011 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. + +// issue 1808 + +package main + +func main() { + var i uint64 + var x int = 12345 + + if y := x << (i&5); y != 12345<<0 { + println("BUG bug344", y) + return + } + + i++ + if y := x << (i&5); y != 12345<<1 { + println("BUG bug344a", y) + } + + i = 70 + if y := x << i; y != 0 { + println("BUG bug344b", y) + } + + i = 1<<32 + if y := x << i; y != 0 { + println("BUG bug344c", y) + } +} + + +/* +typecheck [1008592b0] +. INDREG a(1) l(15) x(24) tc(2) runtime.ret G0 string +bug343.go:15: internal compiler error: typecheck INDREG +*/