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;
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;
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;
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)
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
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);
n->class = PPARAM;
break;
}
+ n->typecheck = 1;
return n;
}
a->name = D_NONE;
a->reg = NREG;
a->node = N;
+ a->etype = 0;
if(n == N)
return;
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;
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;
case OADDR:
naddr(n->left, a, canemitcode);
+ a->etype = tptr;
switch(a->type) {
case D_OREG:
a->type = D_CONST;
a->type = D_NONE;
a->name = D_NONE;
+ n1.type = n->type;
naddr(&n1, a, 1);
goto yes;
a->type = D_OREG;
a->reg = reg->val.u.reg;
a->offset = 0;
-
goto yes;
oindex_const:
int
copyu(Prog *p, Adr *v, Adr *s)
{
-
switch(p->as) {
default:
return 0;
}
if(copyas(&p->to, v)) {
+ if(p->scond != C_SCOND_NONE)
+ return 2;
if(copyau(&p->from, v))
return 4;
return 3;
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))
case AMULD:
case ADIVF:
case ADIVD:
+ case AMULA:
case AMULAL:
case AMULALU:
for(z=0; z<BITS; z++) {
break;
case TBOOL:
case TUINT8:
+//print("movbu %E %d %S\n", v->etype, bn, v->sym);
p1->as = AMOVBU;
break;
case TINT16:
n = D_NONE;
flag = 0;
- if(a->pun)
- flag = 1;
-
switch(t) {
default:
print("type %d %d %D\n", t, a->name, 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;
i = nvar;
nvar++;
+//print("var %d %E %D %S\n", i, et, a, s);
v = var+i;
v->sym = s;
v->offset = o;
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)
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;
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;
}
n->xoffset += types[tptr]->width;
break;
}
+ n->typecheck = 1;
return n;
}
if(debug['g'])
print("%P\n", p);
-
w = 0;
switch(as) {
case AMOVB:
#include "../8l/8.out.h"
#ifndef EXTERN
-#define EXTERN extern
+#define EXTERN extern
#endif
typedef struct Addr Addr;
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)
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);
}
// 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 {
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);
}
}
}
- if(a->pun)
- flag = 1;
switch(et) {
case 0:
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);
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;
--- /dev/null
+// $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
+*/