mirror of
https://github.com/golang/go
synced 2024-11-05 18:36:08 +00:00
cmd/5g, cmd/8g: fix internal error on 64-bit indices statically bounded
Fixes #4448. R=golang-dev, rsc CC=golang-dev https://golang.org/cl/6855100
This commit is contained in:
parent
e781b20ac9
commit
f134742f24
5 changed files with 54 additions and 13 deletions
|
@ -521,7 +521,7 @@ ret:
|
|||
* returns Prog* to patch to panic call.
|
||||
*/
|
||||
Prog*
|
||||
cgenindex(Node *n, Node *res)
|
||||
cgenindex(Node *n, Node *res, int bounded)
|
||||
{
|
||||
Node tmp, lo, hi, zero, n1, n2;
|
||||
|
||||
|
@ -534,7 +534,7 @@ cgenindex(Node *n, Node *res)
|
|||
cgen(n, &tmp);
|
||||
split64(&tmp, &lo, &hi);
|
||||
gmove(&lo, res);
|
||||
if(debug['B']) {
|
||||
if(bounded) {
|
||||
splitclean();
|
||||
return nil;
|
||||
}
|
||||
|
@ -889,6 +889,7 @@ agenr(Node *n, Node *a, Node *res)
|
|||
Prog *p1, *p2;
|
||||
uint32 w;
|
||||
uint64 v;
|
||||
int bounded;
|
||||
|
||||
if(debug['g'])
|
||||
dump("agenr-n", n);
|
||||
|
@ -915,13 +916,14 @@ agenr(Node *n, Node *a, Node *res)
|
|||
case OINDEX:
|
||||
p2 = nil; // to be patched to panicindex.
|
||||
w = n->type->width;
|
||||
bounded = debug['B'] || n->bounded;
|
||||
if(nr->addable) {
|
||||
if(!isconst(nr, CTINT))
|
||||
tempname(&tmp, types[TINT32]);
|
||||
if(!isconst(nl, CTSTR))
|
||||
agenr(nl, &n3, res);
|
||||
if(!isconst(nr, CTINT)) {
|
||||
p2 = cgenindex(nr, &tmp);
|
||||
p2 = cgenindex(nr, &tmp, bounded);
|
||||
regalloc(&n1, tmp.type, N);
|
||||
gmove(&tmp, &n1);
|
||||
}
|
||||
|
@ -929,7 +931,7 @@ agenr(Node *n, Node *a, Node *res)
|
|||
if(nl->addable) {
|
||||
if(!isconst(nr, CTINT)) {
|
||||
tempname(&tmp, types[TINT32]);
|
||||
p2 = cgenindex(nr, &tmp);
|
||||
p2 = cgenindex(nr, &tmp, bounded);
|
||||
regalloc(&n1, tmp.type, N);
|
||||
gmove(&tmp, &n1);
|
||||
}
|
||||
|
@ -938,7 +940,7 @@ agenr(Node *n, Node *a, Node *res)
|
|||
}
|
||||
} else {
|
||||
tempname(&tmp, types[TINT32]);
|
||||
p2 = cgenindex(nr, &tmp);
|
||||
p2 = cgenindex(nr, &tmp, bounded);
|
||||
nr = &tmp;
|
||||
if(!isconst(nl, CTSTR))
|
||||
agenr(nl, &n3, res);
|
||||
|
|
|
@ -88,7 +88,7 @@ void ginscall(Node*, int);
|
|||
* cgen
|
||||
*/
|
||||
void agen(Node*, Node*);
|
||||
Prog* cgenindex(Node *, Node *);
|
||||
Prog* cgenindex(Node *, Node *, int);
|
||||
void igen(Node*, Node*, Node*);
|
||||
void agenr(Node *n, Node *a, Node *res);
|
||||
vlong fieldoffset(Type*, Node*);
|
||||
|
|
|
@ -1937,7 +1937,7 @@ oindex:
|
|||
t = types[TINT32];
|
||||
regalloc(reg1, t, N);
|
||||
regalloc(&n3, types[TINT32], reg1);
|
||||
p2 = cgenindex(r, &n3);
|
||||
p2 = cgenindex(r, &n3, debug['B'] || n->bounded);
|
||||
gmove(&n3, reg1);
|
||||
regfree(&n3);
|
||||
|
||||
|
|
|
@ -464,8 +464,8 @@ flt2: // binary
|
|||
* n is an array index, and might be any size; res width is <= 32-bit.
|
||||
* returns Prog* to patch to panic call.
|
||||
*/
|
||||
Prog*
|
||||
igenindex(Node *n, Node *res)
|
||||
static Prog*
|
||||
igenindex(Node *n, Node *res, int bounded)
|
||||
{
|
||||
Node tmp, lo, hi, zero;
|
||||
|
||||
|
@ -485,7 +485,7 @@ igenindex(Node *n, Node *res)
|
|||
split64(&tmp, &lo, &hi);
|
||||
tempname(res, types[TUINT32]);
|
||||
gmove(&lo, res);
|
||||
if(debug['B']) {
|
||||
if(bounded) {
|
||||
splitclean();
|
||||
return nil;
|
||||
}
|
||||
|
@ -508,6 +508,7 @@ agen(Node *n, Node *res)
|
|||
uint32 w;
|
||||
uint64 v;
|
||||
Prog *p1, *p2;
|
||||
int bounded;
|
||||
|
||||
if(debug['g']) {
|
||||
dump("\nagen-res", res);
|
||||
|
@ -584,26 +585,27 @@ agen(Node *n, Node *res)
|
|||
case OINDEX:
|
||||
p2 = nil; // to be patched to panicindex.
|
||||
w = n->type->width;
|
||||
bounded = debug['B'] || n->bounded;
|
||||
if(nr->addable) {
|
||||
// Generate &nl first, and move nr into register.
|
||||
if(!isconst(nl, CTSTR))
|
||||
igen(nl, &n3, res);
|
||||
if(!isconst(nr, CTINT)) {
|
||||
p2 = igenindex(nr, &tmp);
|
||||
p2 = igenindex(nr, &tmp, bounded);
|
||||
regalloc(&n1, tmp.type, N);
|
||||
gmove(&tmp, &n1);
|
||||
}
|
||||
} else if(nl->addable) {
|
||||
// Generate nr first, and move &nl into register.
|
||||
if(!isconst(nr, CTINT)) {
|
||||
p2 = igenindex(nr, &tmp);
|
||||
p2 = igenindex(nr, &tmp, bounded);
|
||||
regalloc(&n1, tmp.type, N);
|
||||
gmove(&tmp, &n1);
|
||||
}
|
||||
if(!isconst(nl, CTSTR))
|
||||
igen(nl, &n3, res);
|
||||
} else {
|
||||
p2 = igenindex(nr, &tmp);
|
||||
p2 = igenindex(nr, &tmp, bounded);
|
||||
nr = &tmp;
|
||||
if(!isconst(nl, CTSTR))
|
||||
igen(nl, &n3, res);
|
||||
|
|
37
test/fixedbugs/issue4448.go
Normal file
37
test/fixedbugs/issue4448.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
// run
|
||||
|
||||
// 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.
|
||||
|
||||
// Issue 4448: 64-bit indices that are statically known
|
||||
// to be bounded make 5g and 8g generate a dangling branch.
|
||||
|
||||
package main
|
||||
|
||||
const b26 uint64 = 0x022fdd63cc95386d
|
||||
|
||||
var bitPos [64]int
|
||||
|
||||
func init() {
|
||||
for p := uint(0); p < 64; p++ {
|
||||
bitPos[b26<<p>>58] = int(p)
|
||||
}
|
||||
}
|
||||
|
||||
func MinPos(w uint64) int {
|
||||
if w == 0 {
|
||||
panic("bit: MinPos(0) undefined")
|
||||
}
|
||||
return bitPos[((w&-w)*b26)>>58]
|
||||
}
|
||||
|
||||
func main() {
|
||||
const one = uint64(1)
|
||||
for i := 0; i < 64; i++ {
|
||||
if MinPos(1<<uint(i)) != i {
|
||||
println("i =", i)
|
||||
panic("MinPos(1<<uint(i)) != i")
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue