From be443ee8bc64e93bc56d760f3e28f4318c00a8bd Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 12 Sep 2010 00:06:45 -0400 Subject: [PATCH] 5g: register allocation bugs Fixes #1099. R=ken2, r CC=golang-dev https://golang.org/cl/2147047 --- src/cmd/5g/cgen.c | 23 +++++++--- src/cmd/5g/ggen.c | 17 +++++++- src/cmd/5g/gsubr.c | 44 ++++++++++++++++++-- src/cmd/gc/gen.c | 7 ++++ src/pkg/compress/flate/huffman_bit_writer.go | 10 +---- src/pkg/gob/decode.go | 11 ++--- src/pkg/log/log.go | 6 +-- src/pkg/net/ip.go | 14 ++----- src/pkg/time/format.go | 16 +++---- src/pkg/xml/xml.go | 10 +---- 10 files changed, 98 insertions(+), 60 deletions(-) diff --git a/src/cmd/5g/cgen.c b/src/cmd/5g/cgen.c index 310ea99c5b8..9306436ee6d 100644 --- a/src/cmd/5g/cgen.c +++ b/src/cmd/5g/cgen.c @@ -496,6 +496,7 @@ agen(Node *n, Node *res) Prog *p1, *p2; uint32 w; uint64 v; + int r; if(debug['g']) { dump("\nagen-res", res); @@ -527,7 +528,22 @@ agen(Node *n, Node *res) break; 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); break; @@ -536,11 +552,6 @@ agen(Node *n, Node *res) cgen_aret(n, res); break; - case OCALLFUNC: - cgen_call(n, 0); - cgen_aret(n, res); - break; - case OINDEX: p2 = nil; // to be patched to panicindex. w = n->type->width; diff --git a/src/cmd/5g/ggen.c b/src/cmd/5g/ggen.c index c906064584e..77d4e9496f1 100644 --- a/src/cmd/5g/ggen.c +++ b/src/cmd/5g/ggen.c @@ -68,6 +68,7 @@ compile(Node *fn) ptxt = gins(ATEXT, curfn->nname, &nod1); afunclit(&ptxt->from); + ginit(); genlist(curfn->enter); pret = nil; @@ -80,6 +81,7 @@ compile(Node *fn) } genlist(curfn->nbody); + gclean(); checklabels(); if(nerrors != 0) goto ret; @@ -89,10 +91,12 @@ compile(Node *fn) if(pret) patch(pret, pc); + ginit(); if(hasdefer) ginscall(deferreturn, 0); if(curfn->exit) genlist(curfn->exit); + gclean(); if(nerrors != 0) goto ret; if(curfn->endlineno) @@ -207,6 +211,7 @@ ginscall(Node *f, int proc) void cgen_callinter(Node *n, Node *res, int proc) { + int r; Node *i, *f; Node tmpi, nodo, nodr, nodsp; @@ -220,6 +225,14 @@ cgen_callinter(Node *n, Node *res, int proc) 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) { tempname(&tmpi, i->type); cgen(i, &tmpi); @@ -227,6 +240,8 @@ cgen_callinter(Node *n, Node *res, int proc) } genlist(n->list); // args + if(r >= 0) + reg[r]++; regalloc(&nodr, types[tptr], res); regalloc(&nodo, types[tptr], &nodr); @@ -548,7 +563,7 @@ cgen_shift(int op, Node *nl, Node *nr, Node *res) cgen(nl, &n1); sc = mpgetfix(nr->val.u.xval); if(sc == 0) { - return; + // nothing to do } else if(sc >= nl->type->width*8) { if(op == ORSH && issigned[nl->type->etype]) gshift(AMOVW, &n1, SHIFT_AR, w, &n1); diff --git a/src/cmd/5g/gsubr.c b/src/cmd/5g/gsubr.c index 584a0f62b84..88837c35676 100644 --- a/src/cmd/5g/gsubr.c +++ b/src/cmd/5g/gsubr.c @@ -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 closed by ") return false 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 + - // "closed by in space " + name.Space) - str := "element <" + s.name.Local - str += "> in space " + s.name.Space - str += "closed by in space " + name.Space - p.err = p.syntaxError(str) + p.err = p.syntaxError("element <" + s.name.Local + "> in space " + s.name.Space + + "closed by in space " + name.Space) return false }