Commit be443ee8 authored by Russ Cox's avatar Russ Cox

5g: register allocation bugs

Fixes #1099.

R=ken2, r
CC=golang-dev
https://golang.org/cl/2147047
parent b2a65588
...@@ -496,6 +496,7 @@ agen(Node *n, Node *res) ...@@ -496,6 +496,7 @@ agen(Node *n, Node *res)
Prog *p1, *p2; Prog *p1, *p2;
uint32 w; uint32 w;
uint64 v; uint64 v;
int r;
if(debug['g']) { if(debug['g']) {
dump("\nagen-res", res); dump("\nagen-res", res);
...@@ -527,7 +528,22 @@ agen(Node *n, Node *res) ...@@ -527,7 +528,22 @@ agen(Node *n, Node *res)
break; break;
case OCALLMETH: case OCALLMETH:
cgen_callmeth(n, 0); case OCALLFUNC:
// Release res so that it is available for cgen_call.
// Pick it up again after the call.
r = -1;
if(n->ullman >= UINF) {
if(res->op == OREGISTER || res->op == OINDREG) {
r = res->val.u.reg;
reg[r]--;
}
}
if(n->op == OCALLMETH)
cgen_callmeth(n, 0);
else
cgen_call(n, 0);
if(r >= 0)
reg[r]++;
cgen_aret(n, res); cgen_aret(n, res);
break; break;
...@@ -536,11 +552,6 @@ agen(Node *n, Node *res) ...@@ -536,11 +552,6 @@ agen(Node *n, Node *res)
cgen_aret(n, res); cgen_aret(n, res);
break; break;
case OCALLFUNC:
cgen_call(n, 0);
cgen_aret(n, res);
break;
case OINDEX: case OINDEX:
p2 = nil; // to be patched to panicindex. p2 = nil; // to be patched to panicindex.
w = n->type->width; w = n->type->width;
......
...@@ -68,6 +68,7 @@ compile(Node *fn) ...@@ -68,6 +68,7 @@ compile(Node *fn)
ptxt = gins(ATEXT, curfn->nname, &nod1); ptxt = gins(ATEXT, curfn->nname, &nod1);
afunclit(&ptxt->from); afunclit(&ptxt->from);
ginit();
genlist(curfn->enter); genlist(curfn->enter);
pret = nil; pret = nil;
...@@ -80,6 +81,7 @@ compile(Node *fn) ...@@ -80,6 +81,7 @@ compile(Node *fn)
} }
genlist(curfn->nbody); genlist(curfn->nbody);
gclean();
checklabels(); checklabels();
if(nerrors != 0) if(nerrors != 0)
goto ret; goto ret;
...@@ -89,10 +91,12 @@ compile(Node *fn) ...@@ -89,10 +91,12 @@ compile(Node *fn)
if(pret) if(pret)
patch(pret, pc); patch(pret, pc);
ginit();
if(hasdefer) if(hasdefer)
ginscall(deferreturn, 0); ginscall(deferreturn, 0);
if(curfn->exit) if(curfn->exit)
genlist(curfn->exit); genlist(curfn->exit);
gclean();
if(nerrors != 0) if(nerrors != 0)
goto ret; goto ret;
if(curfn->endlineno) if(curfn->endlineno)
...@@ -207,6 +211,7 @@ ginscall(Node *f, int proc) ...@@ -207,6 +211,7 @@ ginscall(Node *f, int proc)
void void
cgen_callinter(Node *n, Node *res, int proc) cgen_callinter(Node *n, Node *res, int proc)
{ {
int r;
Node *i, *f; Node *i, *f;
Node tmpi, nodo, nodr, nodsp; Node tmpi, nodo, nodr, nodsp;
...@@ -220,6 +225,14 @@ cgen_callinter(Node *n, Node *res, int proc) ...@@ -220,6 +225,14 @@ cgen_callinter(Node *n, Node *res, int proc)
i = i->left; // interface i = i->left; // interface
// Release res register during genlist and cgen,
// which might have their own function calls.
r = -1;
if(res != N && (res->op == OREGISTER || res->op == OINDREG)) {
r = res->val.u.reg;
reg[r]--;
}
if(!i->addable) { if(!i->addable) {
tempname(&tmpi, i->type); tempname(&tmpi, i->type);
cgen(i, &tmpi); cgen(i, &tmpi);
...@@ -227,6 +240,8 @@ cgen_callinter(Node *n, Node *res, int proc) ...@@ -227,6 +240,8 @@ cgen_callinter(Node *n, Node *res, int proc)
} }
genlist(n->list); // args genlist(n->list); // args
if(r >= 0)
reg[r]++;
regalloc(&nodr, types[tptr], res); regalloc(&nodr, types[tptr], res);
regalloc(&nodo, types[tptr], &nodr); regalloc(&nodo, types[tptr], &nodr);
...@@ -548,7 +563,7 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res) ...@@ -548,7 +563,7 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res)
cgen(nl, &n1); cgen(nl, &n1);
sc = mpgetfix(nr->val.u.xval); sc = mpgetfix(nr->val.u.xval);
if(sc == 0) { if(sc == 0) {
return; // nothing to do
} else if(sc >= nl->type->width*8) { } else if(sc >= nl->type->width*8) {
if(op == ORSH && issigned[nl->type->etype]) if(op == ORSH && issigned[nl->type->etype])
gshift(AMOVW, &n1, SHIFT_AR, w, &n1); gshift(AMOVW, &n1, SHIFT_AR, w, &n1);
......
...@@ -197,9 +197,50 @@ afunclit(Addr *a) ...@@ -197,9 +197,50 @@ afunclit(Addr *a)
} }
} }
static int resvd[] =
{
9, // reserved for m
10, // reserved for g
};
void
ginit(void)
{
int i;
for(i=0; i<nelem(reg); i++)
reg[i] = 0;
for(i=0; i<nelem(resvd); i++)
reg[resvd[i]]++;
}
void
gclean(void)
{
int i;
for(i=0; i<nelem(resvd); i++)
reg[resvd[i]]--;
for(i=0; i<nelem(reg); i++)
if(reg[i])
yyerror("reg %R left allocated\n", i);
}
int32 int32
anyregalloc(void) anyregalloc(void)
{ {
int i, j;
for(i=0; i<nelem(reg); i++) {
if(reg[i] == 0)
goto ok;
for(j=0; j<nelem(resvd); j++)
if(resvd[j] == i)
goto ok;
return 1;
ok:;
}
return 0; return 0;
} }
...@@ -213,9 +254,6 @@ regalloc(Node *n, Type *t, Node *o) ...@@ -213,9 +254,6 @@ regalloc(Node *n, Type *t, Node *o)
{ {
int i, et, fixfree, floatfree; int i, et, fixfree, floatfree;
// guarantee R9 and R10 (m and g) are left alone. BUG.
reg[9] = 1;
reg[10] = 1;
if(debug['r']) { if(debug['r']) {
fixfree = 0; fixfree = 0;
for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++) for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++)
......
...@@ -139,8 +139,10 @@ gen(Node *n) ...@@ -139,8 +139,10 @@ gen(Node *n)
Prog *scontin, *sbreak; Prog *scontin, *sbreak;
Prog *p1, *p2, *p3; Prog *p1, *p2, *p3;
Label *lab; Label *lab;
int32 wasregalloc;
lno = setlineno(n); lno = setlineno(n);
wasregalloc = anyregalloc();
if(n == N) if(n == N)
goto ret; goto ret;
...@@ -342,6 +344,11 @@ gen(Node *n) ...@@ -342,6 +344,11 @@ gen(Node *n)
} }
ret: ret:
if(anyregalloc() != wasregalloc) {
dump("node", n);
fatal("registers left allocated");
}
lineno = lno; lineno = lno;
} }
......
...@@ -110,14 +110,8 @@ func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter { ...@@ -110,14 +110,8 @@ func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter {
} }
func (err WrongValueError) String() string { func (err WrongValueError) String() string {
// BUG: work around bug in 5g by simplifying expression. return "huffmanBitWriter: " + err.name + " should belong to [" + strconv.Itoa64(int64(err.from)) + ";" +
// return "huffmanBitWriter: " + err.name + " should belong to [" + strconv.Itoa64(int64(err.from)) + ";" + strconv.Itoa64(int64(err.to)) + "] but actual value is " + strconv.Itoa64(int64(err.value))
// strconv.Itoa64(int64(err.to)) + "] but actual value is " + strconv.Itoa64(int64(err.value))
str := "huffmanBitWriter: " + err.name + " should belong to ["
str += strconv.Itoa64(int64(err.from)) + ";"
str += strconv.Itoa64(int64(err.to)) + "] but actual value is "
str += strconv.Itoa64(int64(err.value))
return str
} }
func (w *huffmanBitWriter) flushBits() { func (w *huffmanBitWriter) flushBits() {
......
...@@ -867,14 +867,9 @@ func (dec *Decoder) compileDec(remoteId typeId, rt reflect.Type) (engine *decEng ...@@ -867,14 +867,9 @@ func (dec *Decoder) compileDec(remoteId typeId, rt reflect.Type) (engine *decEng
continue continue
} }
if !dec.compatibleType(localField.Type, wireField.id) { if !dec.compatibleType(localField.Type, wireField.id) {
// BUG: work around bug in 5g by simplifying expression. return nil, os.ErrorString("gob: wrong type (" +
// return nil, os.ErrorString("gob: wrong type (" + localField.Type.String() + ") for received field " +
// localField.Type.String() + ") for received field " + wireStruct.name + "." + wireField.name)
// wireStruct.name + "." + wireField.name)
str := "gob: wrong type ("
str += localField.Type.String() + ") for received field "
str += wireStruct.name + "." + wireField.name
return nil, os.ErrorString(str)
} }
op, indir, err := dec.decOpFor(wireField.id, localField.Type, localField.Name) op, indir, err := dec.decOpFor(wireField.id, localField.Type, localField.Name)
if err != nil { if err != nil {
......
...@@ -86,11 +86,7 @@ func (l *Logger) formatHeader(ns int64, calldepth int) string { ...@@ -86,11 +86,7 @@ func (l *Logger) formatHeader(ns int64, calldepth int) string {
if l.flag&(Ldate|Ltime|Lmicroseconds) != 0 { if l.flag&(Ldate|Ltime|Lmicroseconds) != 0 {
t := time.SecondsToLocalTime(ns / 1e9) t := time.SecondsToLocalTime(ns / 1e9)
if l.flag&(Ldate) != 0 { if l.flag&(Ldate) != 0 {
// BUG: work around bug in 5g by simplifying expression. h += itoa(int(t.Year), 4) + "/" + itoa(t.Month, 2) + "/" + itoa(t.Day, 2) + " "
// h += itoa(int(t.Year), 4) + "/" + itoa(t.Month, 2) + "/" + itoa(t.Day, 2) + " "
h += itoa(int(t.Year), 4)
h += "/" + itoa(t.Month, 2)
h += "/" + itoa(t.Day, 2) + " "
} }
if l.flag&(Ltime|Lmicroseconds) != 0 { if l.flag&(Ltime|Lmicroseconds) != 0 {
h += itoa(t.Hour, 2) + ":" + itoa(t.Minute, 2) + ":" + itoa(t.Second, 2) h += itoa(t.Hour, 2) + ":" + itoa(t.Minute, 2) + ":" + itoa(t.Second, 2)
......
...@@ -200,16 +200,10 @@ func (ip IP) String() string { ...@@ -200,16 +200,10 @@ func (ip IP) String() string {
// If IPv4, use dotted notation. // If IPv4, use dotted notation.
if p4 := p.To4(); len(p4) == 4 { if p4 := p.To4(); len(p4) == 4 {
// BUG: work around bug in 5g by simplifying expression. return itod(uint(p4[0])) + "." +
// return itod(uint(p4[0])) + "." + itod(uint(p4[1])) + "." +
// itod(uint(p4[1])) + "." + itod(uint(p4[2])) + "." +
// itod(uint(p4[2])) + "." + itod(uint(p4[3]))
// itod(uint(p4[3]))
str := itod(uint(p4[0])) + "."
str += itod(uint(p4[1])) + "."
str += itod(uint(p4[2])) + "."
str += itod(uint(p4[3]))
return str
} }
if len(p) != IPv6len { if len(p) != IPv6len {
return "?" return "?"
......
...@@ -356,17 +356,11 @@ type ParseError struct { ...@@ -356,17 +356,11 @@ type ParseError struct {
// String is the string representation of a ParseError. // String is the string representation of a ParseError.
func (e *ParseError) String() string { func (e *ParseError) String() string {
if e.Message == "" { if e.Message == "" {
// BUG: work around bug in 5g by simplifying expression. return "parsing time " +
// return "parsing time " + strconv.Quote(e.Value) + " as " +
// strconv.Quote(e.Value) + " as " + strconv.Quote(e.Layout) + ": cannot parse " +
// strconv.Quote(e.Layout) + ": cannot parse " + strconv.Quote(e.ValueElem) + " as " +
// strconv.Quote(e.ValueElem) + " as " + strconv.Quote(e.LayoutElem)
// strconv.Quote(e.LayoutElem)
str := "parsing time " + strconv.Quote(e.Value) + " as "
str += strconv.Quote(e.Layout) + ": cannot parse "
str += strconv.Quote(e.ValueElem) + " as "
str += strconv.Quote(e.LayoutElem)
return str
} }
return "parsing time " + return "parsing time " +
strconv.Quote(e.Value) + e.Message strconv.Quote(e.Value) + e.Message
......
...@@ -371,14 +371,8 @@ func (p *Parser) popElement(t *EndElement) bool { ...@@ -371,14 +371,8 @@ func (p *Parser) popElement(t *EndElement) bool {
p.err = p.syntaxError("element <" + s.name.Local + "> closed by </" + name.Local + ">") p.err = p.syntaxError("element <" + s.name.Local + "> closed by </" + name.Local + ">")
return false return false
case s.name.Space != name.Space: case s.name.Space != name.Space:
// BUG: work around bug in 5g by simplifying expression. p.err = p.syntaxError("element <" + s.name.Local + "> in space " + s.name.Space +
// p.err = p.syntaxError("element <" + s.name.Local + "> in space " + s.name.Space + "closed by </" + name.Local + "> in space " + name.Space)
// "closed by </" + name.Local + "> in space " + name.Space)
str := "element <" + s.name.Local
str += "> in space " + s.name.Space
str += "closed by </" + name.Local
str += "> in space " + name.Space
p.err = p.syntaxError(str)
return false return false
} }
......
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