]> Cypherpunks repositories - gostls13.git/commitdiff
5g: register allocation bugs
authorRuss Cox <rsc@golang.org>
Sun, 12 Sep 2010 04:06:45 +0000 (00:06 -0400)
committerRuss Cox <rsc@golang.org>
Sun, 12 Sep 2010 04:06:45 +0000 (00:06 -0400)
Fixes #1099.

R=ken2, r
CC=golang-dev
https://golang.org/cl/2147047

src/cmd/5g/cgen.c
src/cmd/5g/ggen.c
src/cmd/5g/gsubr.c
src/cmd/gc/gen.c
src/pkg/compress/flate/huffman_bit_writer.go
src/pkg/gob/decode.go
src/pkg/log/log.go
src/pkg/net/ip.go
src/pkg/time/format.go
src/pkg/xml/xml.go

index 310ea99c5b8429d28895a0e61f634dfcd0b22887..9306436ee6df8389efad63a118ead07c85613003 100644 (file)
@@ -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;
index c906064584e27b380b9d7773e3a4c947c4accd20..77d4e9496f1ba7786991dac818070e32575536aa 100644 (file)
@@ -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);
index 584a0f62b84f1e7ef26b4ff9390e0f40b0ea10b2..88837c35676099cba0b555c1f34a98c48383e728 100644 (file)
@@ -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
 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;
 }
 
@@ -213,9 +254,6 @@ regalloc(Node *n, Type *t, Node *o)
 {
        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']) {
                fixfree = 0;
                for(i=REGALLOC_R0; i<=REGALLOC_RMAX; i++)
index fd8a7f39b432a9e83cedb84e0fd34c3353d6b76c..724f16ae61081cd20228ee0ebb61fb95a76f4ffa 100644 (file)
@@ -139,8 +139,10 @@ gen(Node *n)
        Prog *scontin, *sbreak;
        Prog *p1, *p2, *p3;
        Label *lab;
+       int32 wasregalloc;
 
        lno = setlineno(n);
+       wasregalloc = anyregalloc();
 
        if(n == N)
                goto ret;
@@ -342,6 +344,11 @@ gen(Node *n)
        }
 
 ret:
+       if(anyregalloc() != wasregalloc) {
+               dump("node", n);
+               fatal("registers left allocated");
+       }
+
        lineno = lno;
 }
 
index 294cdf65329d841d5202a331e195e2b454f4cf08..abff82dd694bd21fff203132b3524c652aca428e 100644 (file)
@@ -110,14 +110,8 @@ func newHuffmanBitWriter(w io.Writer) *huffmanBitWriter {
 }
 
 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)) + ";" +
-       //      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
+       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))
 }
 
 func (w *huffmanBitWriter) flushBits() {
index a91a98bf15781bf4ce3fb65ed390c328e397810d..a70799e9a729997d4770fc670629df3756f98180 100644 (file)
@@ -867,14 +867,9 @@ func (dec *Decoder) compileDec(remoteId typeId, rt reflect.Type) (engine *decEng
                        continue
                }
                if !dec.compatibleType(localField.Type, wireField.id) {
-                       // BUG: work around bug in 5g by simplifying expression.
-                       // return nil, os.ErrorString("gob: wrong type (" +
-                       //      localField.Type.String() + ") for received field " +
-                       //      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)
+                       return nil, os.ErrorString("gob: wrong type (" +
+                               localField.Type.String() + ") for received field " +
+                               wireStruct.name + "." + wireField.name)
                }
                op, indir, err := dec.decOpFor(wireField.id, localField.Type, localField.Name)
                if err != nil {
index cfc1bd7767fd27203ee56292e1f35436f4f591f1..28d6204eb68ecee3e5525f18eb2c584426253bf4 100644 (file)
@@ -86,11 +86,7 @@ func (l *Logger) formatHeader(ns int64, calldepth int) string {
        if l.flag&(Ldate|Ltime|Lmicroseconds) != 0 {
                t := time.SecondsToLocalTime(ns / 1e9)
                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)
-                       h += "/" + itoa(t.Month, 2)
-                       h += "/" + itoa(t.Day, 2) + " "
+                       h += itoa(int(t.Year), 4) + "/" + itoa(t.Month, 2) + "/" + itoa(t.Day, 2) + " "
                }
                if l.flag&(Ltime|Lmicroseconds) != 0 {
                        h += itoa(t.Hour, 2) + ":" + itoa(t.Minute, 2) + ":" + itoa(t.Second, 2)
index 29a72971f5ac530e311991fb54de511de52a85ea..e82224a28364274e55fb51b410481b430053ac18 100644 (file)
@@ -200,16 +200,10 @@ func (ip IP) String() string {
 
        // If IPv4, use dotted notation.
        if p4 := p.To4(); len(p4) == 4 {
-               // BUG: work around bug in 5g by simplifying expression.
-               // return itod(uint(p4[0])) + "." +
-               //      itod(uint(p4[1])) + "." +
-               //      itod(uint(p4[2])) + "." +
-               //      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
+               return itod(uint(p4[0])) + "." +
+                       itod(uint(p4[1])) + "." +
+                       itod(uint(p4[2])) + "." +
+                       itod(uint(p4[3]))
        }
        if len(p) != IPv6len {
                return "?"
index bc94cb78e2447bfb9ce2f479edcad320536319af..355721e1839d2725e5a8d59ee91306f7eb4115f2 100644 (file)
@@ -356,17 +356,11 @@ type ParseError struct {
 // String is the string representation of a ParseError.
 func (e *ParseError) String() string {
        if e.Message == "" {
-               // BUG: work around bug in 5g by simplifying expression.
-               // return "parsing time " +
-               //      strconv.Quote(e.Value) + " as " +
-               //      strconv.Quote(e.Layout) + ": cannot parse " +
-               //      strconv.Quote(e.ValueElem) + " as " +
-               //      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 " +
+                       strconv.Quote(e.Value) + " as " +
+                       strconv.Quote(e.Layout) + ": cannot parse " +
+                       strconv.Quote(e.ValueElem) + " as " +
+                       strconv.Quote(e.LayoutElem)
        }
        return "parsing time " +
                strconv.Quote(e.Value) + e.Message
index c72d726c76e7908a637623c14849539b27dcc73c..cd67f6e2657fc9faf5c2960c12f91e0bcded5b10 100644 (file)
@@ -371,14 +371,8 @@ func (p *Parser) popElement(t *EndElement) bool {
                p.err = p.syntaxError("element <" + s.name.Local + "> closed by </" + name.Local + ">")
                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 </" + 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)
+               p.err = p.syntaxError("element <" + s.name.Local + "> in space " + s.name.Space +
+                       "closed by </" + name.Local + "> in space " + name.Space)
                return false
        }