Commit f134742f authored by Rémy Oudompheng's avatar Rémy Oudompheng

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
parent e781b20a
......@@ -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);
......
// 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")
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment