mirror of
https://github.com/golang/go
synced 2024-11-22 02:04:40 -07:00
5g: register allocation bugs
Fixes #1099. R=ken2, r CC=golang-dev https://golang.org/cl/2147047
This commit is contained in:
parent
b2a6558811
commit
be443ee8bc
@ -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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
|
|
||||||
// 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 {
|
|||||||
// 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 {
|
|||||||
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user