]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: minor adjustments for C to Go translation
authorRuss Cox <rsc@golang.org>
Thu, 5 Feb 2015 16:53:33 +0000 (11:53 -0500)
committerRuss Cox <rsc@golang.org>
Fri, 13 Feb 2015 17:31:16 +0000 (17:31 +0000)
- remove a few uses of ? :
- rename variables named len
- rewrite a few gotos as nested switches
- move goto targets to scope allowed by Go
- use consistent return type of anyregalloc
  (was int or int32 in different places)
- remove unused nr variable in agen
- include proper headers in generated builtin1.c
- avoid strange sized %E formats (%-6E, %2E)
- change gengcmask argument from uint8[16] to uint8*
  (diagnosed by c2go; not an array in any real sense).
- replace #ifdef XXX with comment block in 5g/peep.c
- expand and remove FAIL macro from 5g
- expand and remove noimpl macro from 9g
- print regalloc errors to stdout in 8g
  (only use of fprint(2, ...) in all compilers)

Still producing bit-for-bit identical output.

Change-Id: Id46efcd2a89241082b234f63f375b66f2754d695
Reviewed-on: https://go-review.googlesource.com/4646
Reviewed-by: Austin Clements <austin@google.com>
28 files changed:
src/cmd/5g/cgen.c
src/cmd/5g/gsubr.c
src/cmd/5g/peep.c
src/cmd/6g/cgen.c
src/cmd/6g/gsubr.c
src/cmd/6g/peep.c
src/cmd/8g/cgen.c
src/cmd/8g/gsubr.c
src/cmd/9g/cgen.c
src/cmd/9g/gg.h
src/cmd/9g/gsubr.c
src/cmd/9g/peep.c
src/cmd/gc/builtin.c
src/cmd/gc/closure.c
src/cmd/gc/const.c
src/cmd/gc/fmt.c
src/cmd/gc/go.h
src/cmd/gc/lex.c
src/cmd/gc/mkbuiltin
src/cmd/gc/pgen.c
src/cmd/gc/plive.c
src/cmd/gc/popt.c
src/cmd/gc/popt.h
src/cmd/gc/range.c
src/cmd/gc/reflect.c
src/cmd/gc/select.c
src/cmd/gc/swt.c
src/cmd/gc/typecheck.c

index 90cc88d5a7e6a33dfd3701550bd3ad3e257e2939..354e0cbfd69db4019eba875912542fb400b70958 100644 (file)
@@ -1148,27 +1148,20 @@ bgen(Node *n, int true, int likely, Prog *to)
                goto ret;
 
        case OANDAND:
-               if(!true)
-                       goto caseor;
-
-       caseand:
-               p1 = gbranch(AB, T, 0);
-               p2 = gbranch(AB, T, 0);
-               patch(p1, pc);
-               bgen(n->left, !true, -likely, p2);
-               bgen(n->right, !true, -likely, p2);
-               p1 = gbranch(AB, T, 0);
-               patch(p1, to);
-               patch(p2, pc);
-               goto ret;
-
        case OOROR:
-               if(!true)
-                       goto caseand;
-
-       caseor:
-               bgen(n->left, true, likely, to);
-               bgen(n->right, true, likely, to);
+               if((n->op == OANDAND) == true) {
+                       p1 = gbranch(AJMP, T, 0);
+                       p2 = gbranch(AJMP, T, 0);
+                       patch(p1, pc);
+                       bgen(n->left, !true, -likely, p2);
+                       bgen(n->right, !true, -likely, p2);
+                       p1 = gbranch(AJMP, T, 0);
+                       patch(p1, to);
+                       patch(p2, pc);
+               } else {
+                       bgen(n->left, true, likely, to);
+                       bgen(n->right, true, likely, to);
+               }
                goto ret;
 
        case OEQ:
index b7a177d4eac3aa2c57abc5fb442ac136d104b25d..bdb70270a8df9c6b867a58f7b2af5fd2fc9ddc1e 100644 (file)
@@ -69,7 +69,7 @@ gclean(void)
                        yyerror("reg %R left allocated\n", i);
 }
 
-int32
+int
 anyregalloc(void)
 {
        int i, j;
@@ -239,22 +239,25 @@ split64(Node *n, Node *lo, Node *hi)
        nsclean++;
        switch(n->op) {
        default:
-               if(!dotaddable(n, &n1)) {
-                       igen(n, &n1, N);
-                       sclean[nsclean-1] = n1;
-               }
-               n = &n1;
-               goto common;
-       case ONAME:
-               if(n->class == PPARAMREF) {
-                       cgen(n->heapaddr, &n1);
-                       sclean[nsclean-1] = n1;
-                       // fall through.
+               switch(n->op) {
+               default:
+                       if(!dotaddable(n, &n1)) {
+                               igen(n, &n1, N);
+                               sclean[nsclean-1] = n1;
+                       }
                        n = &n1;
+                       break;
+               case ONAME:
+                       if(n->class == PPARAMREF) {
+                               cgen(n->heapaddr, &n1);
+                               sclean[nsclean-1] = n1;
+                               n = &n1;
+                       }
+                       break;
+               case OINDREG:
+                       // nothing
+                       break;
                }
-               goto common;
-       case OINDREG:
-       common:
                *lo = *n;
                *hi = *n;
                lo->type = types[TUINT32];
index fe0969be4b43368076e8d9981a517486d756fa22..7fe3e1071ffe0befd742ba6598fd96101d368bcc 100644 (file)
@@ -122,15 +122,14 @@ loop1:
                        }
                        break;
 
-#ifdef NOTDEF
-XXX
+                       /*
                        if(p->scond == C_SCOND_NONE)
                        if(regtyp(&p->to))
                        if(isdconst(&p->from)) {
                                constprop(&p->from, &p->to, r->s1);
                        }
                        break;
-#endif
+                       */
                }
        }
        if(t)
@@ -562,8 +561,6 @@ gotit:
  * AXXX (x<<y),a,b
  * ..
  */
-#define FAIL(msg) { if(debug['P']) print("\t%s; FAILURE\n", msg); return 0; }
-/*c2go void FAIL(char*); */
 
 int
 shiftprop(Flow *r)
@@ -574,8 +571,11 @@ shiftprop(Flow *r)
        Adr a;
 
        p = r->prog;
-       if(p->to.type != TYPE_REG)
-               FAIL("BOTCH: result not reg");
+       if(p->to.type != TYPE_REG) {
+               if(debug['P'])
+                       print("\tBOTCH: result not reg; FAILURE\n");
+               return 0;
+       }
        n = p->to.reg;
        a = zprog.from;
        if(p->reg != 0 && p->reg != p->to.reg) {
@@ -588,28 +588,43 @@ shiftprop(Flow *r)
        for(;;) {
                /* find first use of shift result; abort if shift operands or result are changed */
                r1 = uniqs(r1);
-               if(r1 == nil)
-                       FAIL("branch");
-               if(uniqp(r1) == nil)
-                       FAIL("merge");
+               if(r1 == nil) {
+                       if(debug['P'])
+                               print("\tbranch; FAILURE\n");
+                       return 0;
+               }
+               if(uniqp(r1) == nil) {
+                       if(debug['P'])
+                               print("\tmerge; FAILURE\n");
+                       return 0;
+               }
                p1 = r1->prog;
                if(debug['P'])
                        print("\n%P", p1);
                switch(copyu(p1, &p->to, nil)) {
                case 0: /* not used or set */
                        if((p->from.type == TYPE_REG && copyu(p1, &p->from, nil) > 1) ||
-                          (a.type == TYPE_REG && copyu(p1, &a, nil) > 1))
-                               FAIL("args modified");
+                          (a.type == TYPE_REG && copyu(p1, &a, nil) > 1)) {
+                               if(debug['P'])
+                                       print("\targs modified; FAILURE\n");
+                               return 0;
+                       }
                        continue;
-               case 3: /* set, not used */
-                       FAIL("BOTCH: noref");
+               case 3: /* set, not used */ {
+                       if(debug['P'])
+                               print("\tBOTCH: noref; FAILURE\n");
+                       return 0;
+               }
                }
                break;
        }
        /* check whether substitution can be done */
        switch(p1->as) {
        default:
-               FAIL("non-dpi");
+               if(debug['P'])
+                       print("\tnon-dpi; FAILURE\n");
+               return 0;
+
        case AAND:
        case AEOR:
        case AADD:
@@ -620,8 +635,11 @@ shiftprop(Flow *r)
        case ARSB:
        case ARSC:
                if(p1->reg == n || (p1->reg == 0 && p1->to.type == TYPE_REG && p1->to.reg == n)) {
-                       if(p1->from.type != TYPE_REG)
-                               FAIL("can't swap");
+                       if(p1->from.type != TYPE_REG) {
+                               if(debug['P'])
+                                       print("\tcan't swap; FAILURE\n");
+                               return 0;
+                       }
                        p1->reg = p1->from.reg;
                        p1->from.reg = n;
                        switch(p1->as) {
@@ -645,15 +663,27 @@ shiftprop(Flow *r)
        case ATST:
        case ACMP:
        case ACMN:
-               if(p1->reg == n)
-                       FAIL("can't swap");
-               if(p1->reg == 0 && p1->to.reg == n)
-                       FAIL("shift result used twice");
+               if(p1->reg == n) {
+                       if(debug['P'])
+                               print("\tcan't swap; FAILURE\n");
+                       return 0;
+               }
+               if(p1->reg == 0 && p1->to.reg == n) {
+                       if(debug['P'])
+                               print("\tshift result used twice; FAILURE\n");
+                       return 0;
+               }
 //     case AMVN:
-               if(p1->from.type == TYPE_SHIFT)
-                       FAIL("shift result used in shift");
-               if(p1->from.type != TYPE_REG || p1->from.reg != n)
-                       FAIL("BOTCH: where is it used?");
+               if(p1->from.type == TYPE_SHIFT) {
+                       if(debug['P'])
+                               print("\tshift result used in shift; FAILURE\n");
+                       return 0;
+               }
+               if(p1->from.type != TYPE_REG || p1->from.reg != n) {
+                       if(debug['P'])
+                               print("\tBOTCH: where is it used?; FAILURE\n");
+                       return 0;
+               }
                break;
        }
        /* check whether shift result is used subsequently */
@@ -661,8 +691,11 @@ shiftprop(Flow *r)
        if(p1->to.reg != n)
        for (;;) {
                r1 = uniqs(r1);
-               if(r1 == nil)
-                       FAIL("inconclusive");
+               if(r1 == nil) {
+                       if(debug['P'])
+                               print("\tinconclusive; FAILURE\n");
+                       return 0;
+               }
                p1 = r1->prog;
                if(debug['P'])
                        print("\n%P", p1);
@@ -672,7 +705,9 @@ shiftprop(Flow *r)
                case 3: /* set, not used */
                        break;
                default:/* used */
-                       FAIL("reused");
+                       if(debug['P'])
+                               print("\treused; FAILURE\n");
+                       return 0;
                }
                break;
        }
index 2a25724361ea01f3a52e4cb3403487dd2bd93581..77ab2d2167a52313caf31734efee19756ce8bcad 100644 (file)
@@ -790,7 +790,7 @@ agenr(Node *n, Node *a, Node *res)
 void
 agen(Node *n, Node *res)
 {
-       Node *nl, *nr;
+       Node *nl;
        Node n1, n2;
 
        if(debug['g']) {
@@ -827,8 +827,6 @@ agen(Node *n, Node *res)
        }
 
        nl = n->left;
-       nr = n->right;
-       USED(nr);
 
        switch(n->op) {
        default:
@@ -1065,17 +1063,7 @@ bgen(Node *n, int true, int likely, Prog *to)
 
        switch(n->op) {
        default:
-       def:
-               regalloc(&n1, n->type, N);
-               cgen(n, &n1);
-               nodconst(&n2, n->type, 0);
-               gins(optoas(OCMP, n->type), &n1, &n2);
-               a = AJNE;
-               if(!true)
-                       a = AJEQ;
-               patch(gbranch(a, n->type, likely), to);
-               regfree(&n1);
-               goto ret;
+               goto def;
 
        case OLITERAL:
                // need to ask if it is bool?
@@ -1095,27 +1083,20 @@ bgen(Node *n, int true, int likely, Prog *to)
                goto ret;
 
        case OANDAND:
-               if(!true)
-                       goto caseor;
-
-       caseand:
-               p1 = gbranch(AJMP, T, 0);
-               p2 = gbranch(AJMP, T, 0);
-               patch(p1, pc);
-               bgen(n->left, !true, -likely, p2);
-               bgen(n->right, !true, -likely, p2);
-               p1 = gbranch(AJMP, T, 0);
-               patch(p1, to);
-               patch(p2, pc);
-               goto ret;
-
        case OOROR:
-               if(!true)
-                       goto caseand;
-
-       caseor:
-               bgen(n->left, true, likely, to);
-               bgen(n->right, true, likely, to);
+               if((n->op == OANDAND) == true) {
+                       p1 = gbranch(AJMP, T, 0);
+                       p2 = gbranch(AJMP, T, 0);
+                       patch(p1, pc);
+                       bgen(n->left, !true, -likely, p2);
+                       bgen(n->right, !true, -likely, p2);
+                       p1 = gbranch(AJMP, T, 0);
+                       patch(p1, to);
+                       patch(p2, pc);
+               } else {
+                       bgen(n->left, true, likely, to);
+                       bgen(n->right, true, likely, to);
+               }
                goto ret;
 
        case OEQ:
@@ -1273,6 +1254,18 @@ bgen(Node *n, int true, int likely, Prog *to)
        }
        goto ret;
 
+def:
+       regalloc(&n1, n->type, N);
+       cgen(n, &n1);
+       nodconst(&n2, n->type, 0);
+       gins(optoas(OCMP, n->type), &n1, &n2);
+       a = AJNE;
+       if(!true)
+               a = AJEQ;
+       patch(gbranch(a, n->type, likely), to);
+       regfree(&n1);
+       goto ret;
+
 ret:
        ;
 }
index 725ed8f819dce700867136a61cce37c8a980fb55..55d3425081b86b9ce97cc300931a36e1460aa155 100644 (file)
@@ -95,7 +95,7 @@ gclean(void)
                        yyerror("reg %R left allocated\n", i);
 }
 
-int32
+int
 anyregalloc(void)
 {
        int i, j;
index 1140a3d4bb9c0cb9c2cb5fdd56e545344451238d..261cb6e0a1901306a70ad24d2ee1e1ae2319d10e 100644 (file)
@@ -767,7 +767,7 @@ copyu(Prog *p, Adr *v, Adr *s)
        case ACALL:
                if(REGEXT && v->type == TYPE_REG && v->reg <= REGEXT && v->reg > exregoffset)
                        return 2;
-               if(REGARG >= 0 && v->type == TYPE_REG && v->reg == (uchar)REGARG)
+               if(REGARG >= 0 && v->type == TYPE_REG && v->reg == REGARG)
                        return 2;
                if(v->type == p->from.type && v->reg == p->from.reg)
                        return 2;
@@ -782,7 +782,7 @@ copyu(Prog *p, Adr *v, Adr *s)
                return 3;
 
        case ATEXT:
-               if(REGARG >= 0 && v->type == TYPE_REG && v->reg == (uchar)REGARG)
+               if(REGARG >= 0 && v->type == TYPE_REG && v->reg == REGARG)
                        return 3;
                return 0;
        }
index c38aa0bcc1b4644fe7360efb1f9dd180b8ec1e27..f06927c90530c6a7e101610904fbc46463e7d5c1 100644 (file)
@@ -956,17 +956,7 @@ bgen(Node *n, int true, int likely, Prog *to)
 
        switch(n->op) {
        default:
-       def:
-               regalloc(&n1, n->type, N);
-               cgen(n, &n1);
-               nodconst(&n2, n->type, 0);
-               gins(optoas(OCMP, n->type), &n1, &n2);
-               a = AJNE;
-               if(!true)
-                       a = AJEQ;
-               patch(gbranch(a, n->type, likely), to);
-               regfree(&n1);
-               return;
+               goto def;
 
        case OLITERAL:
                // need to ask if it is bool?
@@ -986,27 +976,20 @@ bgen(Node *n, int true, int likely, Prog *to)
                return;
 
        case OANDAND:
-               if(!true)
-                       goto caseor;
-
-       caseand:
-               p1 = gbranch(AJMP, T, 0);
-               p2 = gbranch(AJMP, T, 0);
-               patch(p1, pc);
-               bgen(n->left, !true, -likely, p2);
-               bgen(n->right, !true, -likely, p2);
-               p1 = gbranch(AJMP, T, 0);
-               patch(p1, to);
-               patch(p2, pc);
-               return;
-
        case OOROR:
-               if(!true)
-                       goto caseand;
-
-       caseor:
-               bgen(n->left, true, likely, to);
-               bgen(n->right, true, likely, to);
+               if((n->op == OANDAND) == true) {
+                       p1 = gbranch(AJMP, T, 0);
+                       p2 = gbranch(AJMP, T, 0);
+                       patch(p1, pc);
+                       bgen(n->left, !true, -likely, p2);
+                       bgen(n->right, !true, -likely, p2);
+                       p1 = gbranch(AJMP, T, 0);
+                       patch(p1, to);
+                       patch(p2, pc);
+               } else {
+                       bgen(n->left, true, likely, to);
+                       bgen(n->right, true, likely, to);
+               }
                return;
 
        case OEQ:
@@ -1150,6 +1133,19 @@ cmp:
                regfree(nr);
                break;
        }
+       return;
+
+def:
+       regalloc(&n1, n->type, N);
+       cgen(n, &n1);
+       nodconst(&n2, n->type, 0);
+       gins(optoas(OCMP, n->type), &n1, &n2);
+       a = AJNE;
+       if(!true)
+               a = AJEQ;
+       patch(gbranch(a, n->type, likely), to);
+       regfree(&n1);
+       return;
 }
 
 /*
index 959ef20592c42f97ae0a3bee540ddd75f102d8e4..b82f7622ef635db123ebeccfe38b2791b84d8a63 100644 (file)
@@ -667,7 +667,7 @@ gclean(void)
                        yyerror("reg %R left allocated\n", i);
 }
 
-int32
+int
 anyregalloc(void)
 {
        int i, j;
@@ -724,9 +724,9 @@ regalloc(Node *n, Type *t, Node *o)
                        if(reg[i] == 0)
                                goto out;
 
-               fprint(2, "registers allocated at\n");
+               print("registers allocated at\n");
                for(i=REG_AX; i<=REG_DI; i++)
-                       fprint(2, "\t%R\t%#lux\n", i, regpc[i]);
+                       print("\t%R\t%#lux\n", i, regpc[i]);
                fatal("out of fixed registers");
                goto err;
 
@@ -744,9 +744,9 @@ regalloc(Node *n, Type *t, Node *o)
                for(i=REG_X0; i<=REG_X7; i++)
                        if(reg[i] == 0)
                                goto out;
-               fprint(2, "registers allocated at\n");
+               print("registers allocated at\n");
                for(i=REG_X0; i<=REG_X7; i++)
-                       fprint(2, "\t%R\t%#lux\n", i, regpc[i]);
+                       print("\t%R\t%#lux\n", i, regpc[i]);
                fatal("out of floating registers");
        }
        yyerror("regalloc: unknown type %T", t);
@@ -853,22 +853,25 @@ split64(Node *n, Node *lo, Node *hi)
        nsclean++;
        switch(n->op) {
        default:
-               if(!dotaddable(n, &n1)) {
-                       igen(n, &n1, N);
-                       sclean[nsclean-1] = n1;
-               }
-               n = &n1;
-               goto common;
-       case ONAME:
-               if(n->class == PPARAMREF) {
-                       cgen(n->heapaddr, &n1);
-                       sclean[nsclean-1] = n1;
-                       // fall through.
+               switch(n->op) {
+               default:
+                       if(!dotaddable(n, &n1)) {
+                               igen(n, &n1, N);
+                               sclean[nsclean-1] = n1;
+                       }
                        n = &n1;
+                       break;
+               case ONAME:
+                       if(n->class == PPARAMREF) {
+                               cgen(n->heapaddr, &n1);
+                               sclean[nsclean-1] = n1;
+                               n = &n1;
+                       }
+                       break;
+               case OINDREG:
+                       // nothing
+                       break;
                }
-               goto common;
-       case OINDREG:
-       common:
                *lo = *n;
                *hi = *n;
                lo->type = types[TUINT32];
@@ -1466,7 +1469,7 @@ floatmove_387(Node *f, Node *t)
                gmove(f, &t1);
                switch(tt) {
                default:
-                       fatal("gmove %T", t);
+                       fatal("gmove %N", t);
                case TINT8:
                        gins(ACMPL, &t1, ncon(-0x80));
                        p1 = gbranch(optoas(OLT, types[TINT32]), T, -1);
index b73f207fb3a48c7d638c63c0a7683416dcdafc8d..009ea1ed7ad34600f397d6297de4ba3dab29d35f 100644 (file)
@@ -805,7 +805,7 @@ ginsadd(int as, vlong off, Node *dst)
 void
 agen(Node *n, Node *res)
 {
-       Node *nl, *nr;
+       Node *nl;
        Node n1, n2, n3;
 
        if(debug['g']) {
@@ -848,8 +848,6 @@ agen(Node *n, Node *res)
        }
 
        nl = n->left;
-       nr = n->right;
-       USED(nr);
 
        switch(n->op) {
        default:
@@ -1109,27 +1107,20 @@ bgen(Node *n, int true, int likely, Prog *to)
                goto ret;
 
        case OANDAND:
-               if(!true)
-                       goto caseor;
-
-       caseand:
-               p1 = gbranch(ABR, T, 0);
-               p2 = gbranch(ABR, T, 0);
-               patch(p1, pc);
-               bgen(n->left, !true, -likely, p2);
-               bgen(n->right, !true, -likely, p2);
-               p1 = gbranch(ABR, T, 0);
-               patch(p1, to);
-               patch(p2, pc);
-               goto ret;
-
        case OOROR:
-               if(!true)
-                       goto caseand;
-
-       caseor:
-               bgen(n->left, true, likely, to);
-               bgen(n->right, true, likely, to);
+               if((n->op == OANDAND) == true) {
+                       p1 = gbranch(AJMP, T, 0);
+                       p2 = gbranch(AJMP, T, 0);
+                       patch(p1, pc);
+                       bgen(n->left, !true, -likely, p2);
+                       bgen(n->right, !true, -likely, p2);
+                       p1 = gbranch(AJMP, T, 0);
+                       patch(p1, to);
+                       patch(p2, pc);
+               } else {
+                       bgen(n->left, true, likely, to);
+                       bgen(n->right, true, likely, to);
+               }
                goto ret;
 
        case OEQ:
index cc44f3586c16ab3fed97f07b54401c59037a503c..938675937e478891e46fa46ec867b56f7736bb62 100644 (file)
@@ -9,9 +9,6 @@
 #include "../gc/go.h"
 #include "../9l/9.out.h"
 
-// TODO(minux): Remove when no longer used.
-#define noimpl sysfatal("%s not implemented (%s:%d).", __func__, __FILE__, __LINE__)
-
 EXTERN uchar   reg[NREG+NFREG];
 EXTERN Node*   panicdiv;
 extern vlong   unmappedzero;
index e01b587031e65a4ce2543249b7f02f084a6f5b34..1fb15113614550d0653b08c4d4f00b5be84fc49b 100644 (file)
@@ -87,7 +87,7 @@ gclean(void)
                        yyerror("reg %R left allocated, %p\n", i+REG_R0, regpc[i]);
 }
 
-int32
+int
 anyregalloc(void)
 {
        int i, j;
@@ -732,8 +732,7 @@ fixlargeoffset(Node *n)
        if(n->xoffset != (int32)n->xoffset) {
                // TODO(minux): offset too large, move into R31 and add to R31 instead.
                // this is used only in test/fixedbugs/issue6036.go.
-               print("offset too large: %N\n", n);
-               noimpl;
+               fatal("offset too large: %N", n);
                a = *n;
                a.op = OREGISTER;
                a.type = types[tptr];
index 0980039c9d37c6bb68063183f74b8a5d3e384d95..cf96d5dcda7cc8d740b4c44e543665d94eb275c0 100644 (file)
@@ -575,7 +575,7 @@ copyu(Prog *p, Addr *v, Addr *s)
 {
        if(p->from3.type != TYPE_NONE)
                // 9g never generates a from3
-               print("copyu: from3 (%D) not implemented\n", p->from3);
+               print("copyu: from3 (%D) not implemented\n", &p->from3);
 
        switch(p->as) {
 
index d381566d1fab3c244d2d0664341152a3353e7ab6..1178f622e5a8f3e0b410e123e8f72fe69d1d08e0 100644 (file)
@@ -1,4 +1,7 @@
 // AUTO-GENERATED by mkbuiltin; DO NOT EDIT
+#include <u.h>
+#include <libc.h>
+#include "go.h"
 char *runtimeimport =
        "package runtime\n"
        "import runtime \"runtime\"\n"
index eb72ea14ce37b346b3694e062f633f9cca5f4e53..0391ece3791e7fd083a74a8325c2aec546f6c575 100644 (file)
@@ -208,10 +208,19 @@ capturevars(Node *xfunc)
                        v->closure->addrtaken = 1;
                        outer = nod(OADDR, outer, N);
                }
-               if(debug['m'] > 1)
+               if(debug['m'] > 1) {
+                       Sym *name;
+                       char *how;
+                       name = nil;
+                       if(v->curfn && v->curfn->nname)
+                               name = v->curfn->nname->sym;
+                       how = "ref";
+                       if(v->byval)
+                               how = "value";
                        warnl(v->lineno, "%S capturing by %s: %S (addr=%d assign=%d width=%d)",
-                               (v->curfn && v->curfn->nname) ? v->curfn->nname->sym : S, v->byval ? "value" : "ref",
+                               name, how,
                                v->sym, v->closure->addrtaken, v->closure->assigned, (int32)v->type->width);
+               }
                typecheck(&outer, Erv);
                func->enter = list(func->enter, outer);
        }
index e418b9c561e9052a59adbb91e04d3b149700e94e..50accb93a3eca084ed566d1995a3062c2631d61f 100644 (file)
@@ -696,14 +696,7 @@ evconst(Node *n)
        // run op
        switch(TUP(n->op, v.ctype)) {
        default:
-       illegal:
-               if(!n->diag) {
-                       yyerror("illegal constant expression: %T %O %T",
-                               nl->type, n->op, nr->type);
-                       n->diag = 1;
-               }
-               return;
-
+               goto illegal;
        case TUP(OADD, CTINT):
        case TUP(OADD, CTRUNE):
                mpaddfixfix(v.u.xval, rv.u.xval, 0);
@@ -1036,6 +1029,14 @@ setfalse:
        *n = *nodbool(0);
        n->orig = norig;
        return;
+
+illegal:
+       if(!n->diag) {
+               yyerror("illegal constant expression: %T %O %T",
+                       nl->type, n->op, nr->type);
+               n->diag = 1;
+       }
+       return;
 }
 
 Node*
@@ -1214,28 +1215,31 @@ defaultlit(Node **np, Type *t)
        case CTCPLX:
                t1 = types[TCOMPLEX128];
                goto num;
-       num:
-               if(t != T) {
-                       if(isint[t->etype]) {
-                               t1 = t;
-                               n->val = toint(n->val);
-                       }
-                       else
-                       if(isfloat[t->etype]) {
-                               t1 = t;
-                               n->val = toflt(n->val);
-                       }
-                       else
-                       if(iscomplex[t->etype]) {
-                               t1 = t;
-                               n->val = tocplx(n->val);
-                       }
+       }
+       lineno = lno;
+       return;
+
+num:
+       if(t != T) {
+               if(isint[t->etype]) {
+                       t1 = t;
+                       n->val = toint(n->val);
+               }
+               else
+               if(isfloat[t->etype]) {
+                       t1 = t;
+                       n->val = toflt(n->val);
+               }
+               else
+               if(iscomplex[t->etype]) {
+                       t1 = t;
+                       n->val = tocplx(n->val);
                }
-               overflow(n->val, t1);
-               convlit(np, t1);
-               break;
        }
+       overflow(n->val, t1);
+       convlit(np, t1);
        lineno = lno;
+       return;
 }
 
 /*
index f9eb0ba2b3806cd2a673a22e4c8cd6d1d5b84af0..bd0a29f6e148c48d746ff3f5f9cad3ac47ffa04a 100644 (file)
@@ -171,7 +171,7 @@ goopnames[] =
 };
 
 // Fmt "%O":  Node opcodes
-static int
+int
 Oconv(Fmt *fp)
 {
        int o;
@@ -1558,7 +1558,7 @@ Sconv(Fmt *fp)
 // Flags: 'l' print definition, not name
 //       'h' omit 'func' and receiver from function types, short type names
 //       'u' package name, not prefix (FTypeId mode, sticky)
-static int
+int
 Tconv(Fmt *fp)
 {
        Type *t;
index d99a7d431fbf8a50cf435943e0fa866ccd0aae8f..c5ef74586d0224e828be50030e8fce6c6d831232 100644 (file)
@@ -743,6 +743,7 @@ struct      Var
        Node*   node;
        Var*    nextinnode;
        int     width;
+       int     id;
        char    name;
        char    etype;
        char    addr;
@@ -1732,6 +1733,13 @@ void datagostring(Strlit *sval, Addr *a);
 int ismem(Node*);
 int samereg(Node*, Node*);
 void   regopt(Prog*);
+int    Tconv(Fmt*);
+int    Oconv(Fmt*);
+Prog*  gbranch(int as, Type *t, int likely);
+void   nodindreg(Node *n, Type *t, int r);
+void   nodreg(Node *n, Type *t, int r);
+Prog*  prog(int as);
+void   datastring(char*, int, Addr*);
 
 EXTERN int32   pcloc;
 
index b915e9fed2aa52c5b50c13be55943dc00c6aa68d..a4b832aa0bd2b0a3585f951a732aaf9203339d0c 100644 (file)
@@ -660,7 +660,7 @@ importfile(Val *f, int line)
        Biobuf *imp;
        char *file, *p, *q, *tag;
        int32 c;
-       int len;
+       int n;
        Strlit *path;
        char *cleanbuf, *prefix;
 
@@ -758,8 +758,8 @@ importfile(Val *f, int line)
        }
        file = strdup(namebuf);
 
-       len = strlen(namebuf);
-       if(len > 2 && namebuf[len-2] == '.' && namebuf[len-1] == 'a') {
+       n = strlen(namebuf);
+       if(n > 2 && namebuf[n-2] == '.' && namebuf[n-1] == 'a') {
                if(!skiptopkgdef(imp)) {
                        yyerror("import %s: not a package file", file);
                        errorexit();
@@ -783,7 +783,7 @@ importfile(Val *f, int line)
 
        // assume files move (get installed)
        // so don't record the full path.
-       linehist(file + len - path->len - 2, -1, 1);    // acts as #pragma lib
+       linehist(file + n - path->len - 2, -1, 1);      // acts as #pragma lib
 
        /*
         * position the input right
@@ -987,17 +987,7 @@ l0:
                        rune = c;
                        clen += runetochar(cp+clen, &rune);
                }
-
-       strlit:
-               *(int32*)cp = clen-sizeof(int32);       // length
-               do {
-                       cp[clen++] = 0;
-               } while(clen & MAXALIGN);
-               yylval.val.u.sval = (Strlit*)cp;
-               yylval.val.ctype = CTSTR;
-               DBG("lex: string literal\n");
-               strcpy(litbuf, "string literal");
-               return LLITERAL;
+               goto strlit;
 
        case '\'':
                /* '.' */
@@ -1292,7 +1282,7 @@ talph:
                if(c >= Runeself) {
                        ungetc(c);
                        rune = getr();
-                       // 0xb7 Ã‚· is used for internal names
+                       // 0xb7 Â· is used for internal names
                        if(!isalpharune(rune) && !isdigitrune(rune) && (importpkg == nil || rune != 0xb7))
                                yyerror("invalid identifier character U+%04x", rune);
                        cp += runetochar(cp, &rune);
@@ -1480,6 +1470,17 @@ caseout:
        strcpy(litbuf, "literal ");
        strcat(litbuf, lexbuf);
        return LLITERAL;
+
+strlit:
+       *(int32*)cp = clen-sizeof(int32);       // length
+       do {
+               cp[clen++] = 0;
+       } while(clen & MAXALIGN);
+       yylval.val.u.sval = (Strlit*)cp;
+       yylval.val.ctype = CTSTR;
+       DBG("lex: string literal\n");
+       strcpy(litbuf, "string literal");
+       return LLITERAL;
 }
 
 static void pragcgo(char*);
index 1dab1c9a05053aeaffb6b8e9bc1841a7be5f0782..696aa824243beaadb77f5002eefda200b662fa72 100755 (executable)
@@ -20,6 +20,10 @@ GC=${GOCHAR}g
 gcc -o mkbuiltin1 mkbuiltin1.c
 rm -f _builtin.c
 echo "// AUTO-GENERATED by mkbuiltin; DO NOT EDIT" >>_builtin.c
+echo "#include <u.h>" >>_builtin.c
+echo "#include <libc.h>" >>_builtin.c
+echo '#include "go.h"' >>_builtin.c
+
 for i in runtime unsafe
 do
        go tool $GC -A $i.go
index 371db2895fa91dad41817acc493f6fb65f430da6..3df78e7f9a2d917eb9eb2fcf771bfe2569f33811 100644 (file)
@@ -161,6 +161,7 @@ compile(Node *fn)
        Iter save;
        vlong oldstksize;
        NodeList *l;
+       Node *nam;
        Sym *gcargs;
        Sym *gclocals;
 
@@ -229,7 +230,10 @@ compile(Node *fn)
        setlineno(curfn);
 
        nodconst(&nod1, types[TINT32], 0);
-       ptxt = thearch.gins(ATEXT, isblank(curfn->nname) ? N : curfn->nname, &nod1);
+       nam = curfn->nname;
+       if(isblank(nam))
+               nam = N;
+       ptxt = thearch.gins(ATEXT, nam, &nod1);
        if(fn->dupok)
                ptxt->from3.offset |= DUPOK;
        if(fn->wrapper)
index 283c5125e3bdd2976a66ba596807e0966ba469b4..c0d1e579328b962313b539ed3a168db3804cd26d 100644 (file)
@@ -1909,15 +1909,15 @@ static void
 twobitwritesymbol(Array *arr, Sym *sym)
 {
        Bvec *bv;
-       int off, i, j, len;
+       int off, i, j, n;
        uint32 word;
 
-       len = arraylength(arr);
+       n = arraylength(arr);
        off = 0;
        off += 4; // number of bitmaps, to fill in later
        bv = *(Bvec**)arrayget(arr, 0);
        off = duint32(sym, off, bv->n); // number of bits in each bitmap
-       for(i = 0; i < len; i++) {
+       for(i = 0; i < n; i++) {
                // bitmap words
                bv = *(Bvec**)arrayget(arr, i);
                if(bv == nil)
index af7e5b1ff337c036beb9664d6b6bff3dadc9c1d3..b02d58e663bc454c8fe028fe8ab7c532e60d783b 100644 (file)
@@ -782,10 +782,9 @@ mergetemp(Prog *firstp)
        }
 
        // Clear aux structures.
-       for(i = 0; i < nvar; i++) {
-               v = &var[i];
-               v->node->opt = nil;
-       }
+       for(i = 0; i < nvar; i++)
+               var[i].node->opt = nil;
+
        free(var);
        free(bystart);
        free(inuse);
index 2bae0d770ded2867545b3f62da883c03ea671612..0a30e81f5513087d20df70f906e5d879b5367183 100644 (file)
 #define        Z       N
 #define        Adr     Addr
 
-#define        D_HI    TYPE_NONE
-#define        D_LO    TYPE_NONE
-
 #define        BLOAD(r)        band(bnot(r->refbehind), r->refahead)
 #define        BSTORE(r)       band(bnot(r->calbehind), r->calahead)
 #define        LOAD(r)         (~r->refbehind.b[z] & r->refahead.b[z])
 #define        STORE(r)        (~r->calbehind.b[z] & r->calahead.b[z])
 
-#define        CLOAD   5
-#define        CREF    5
-#define        CINF    1000
-#define        LOOP    3
-
-typedef        struct  Reg     Reg;
-typedef        struct  Rgn     Rgn;
-
-/*c2go
-extern Node *Z;
 enum
 {
-       D_HI = TYPE_NONE,
-       D_LO = TYPE_NONE,
        CLOAD = 5,
        CREF = 5,
        CINF = 1000,
        LOOP = 3,
 };
 
+typedef        struct  Reg     Reg;
+typedef        struct  Rgn     Rgn;
+
+/*c2go
+extern Node *Z;
+
 uint32 BLOAD(Reg*);
 uint32 BSTORE(Reg*);
 uint64 LOAD(Reg*);
index ff05820b58b00d0dd0c34f7d5a27a689f46e3154..ff9de6c34973113a2b6cb602e175fd4ab3fa8d0b 100644 (file)
@@ -13,6 +13,7 @@
 void
 typecheckrange(Node *n)
 {
+       int toomany;
        char *why;
        Type *t, *t1, *t2;
        Node *v1, *v2;
@@ -41,6 +42,7 @@ typecheckrange(Node *n)
                t = t->type;
        n->type = t;
 
+       toomany = 0;
        switch(t->etype) {
        default:
                yyerror("cannot range over %lN", n->right);
@@ -64,7 +66,7 @@ typecheckrange(Node *n)
                t1 = t->type;
                t2 = nil;
                if(count(n->list) == 2)
-                       goto toomany;
+                       toomany = 1;
                break;
 
        case TSTRING:
@@ -73,10 +75,8 @@ typecheckrange(Node *n)
                break;
        }
 
-       if(count(n->list) > 2) {
-       toomany:
+       if(count(n->list) > 2 || toomany)
                yyerror("too many variables in range");
-       }
 
        v1 = N;
        if(n->list)
index 7f81e676f988919172cc5f067d4699562f54a2fb..14a1f13e33c0da035157a41cdf882f04263ab373 100644 (file)
@@ -1349,7 +1349,7 @@ usegcprog(Type *t)
 
 // Generates sparse GC bitmask (4 bits per word).
 static void
-gengcmask(Type *t, uint8 gcmask[16])
+gengcmask(Type *t, uint8 *gcmask)
 {
        Bvec *vec;
        vlong xoffset, nptr, i, j;
index 5d3b71164a54b6fe2fbc7256f0690614928d633c..537d0ca928e5b00e41271453b8d38e64e6a5c4dc 100644 (file)
@@ -133,18 +133,16 @@ walkselect(Node *sel)
                                break;
 
                        case OSELRECV:
-                               ch = n->right->left;
-                       Selrecv1:
-                               if(n->left == N)
-                                       n = n->right;
-                               else
-                                       n->op = OAS;
-                               break;
-                       
                        case OSELRECV2:
                                ch = n->right->left;
-                               if(n->ntest == N)
-                                       goto Selrecv1;
+                               if(n->op == OSELRECV || n->ntest == N) {
+                                       if(n->left == N)
+                                               n = n->right;
+                                       else
+                                               n->op = OAS;
+                                       break;
+                               }
+                       
                                if(n->left == N) {
                                        typecheck(&nblank, Erv | Easgn);
                                        n->left = nblank;
index e75971d477214a568dd6f50e52ed55b475729bcc..0dc0065ed92b36b4a2429daf4a1c114e3f144980 100644 (file)
@@ -454,31 +454,22 @@ exprbsw(Case *c0, int ncase, int arg)
                        n = c0->node;
                        lno = setlineno(n);
 
-                       if(assignop(n->left->type, exprname->type, nil) == OCONVIFACE ||
-                          assignop(exprname->type, n->left->type, nil) == OCONVIFACE)
-                               goto snorm;
-
-                       switch(arg) {
-                       case Strue:
+                       if((arg != Strue && arg != Sfalse) ||
+                          assignop(n->left->type, exprname->type, nil) == OCONVIFACE ||
+                          assignop(exprname->type, n->left->type, nil) == OCONVIFACE) {
                                a = nod(OIF, N, N);
-                               a->ntest = n->left;                     // if val
+                               a->ntest = nod(OEQ, exprname, n->left); // if name == val
+                               typecheck(&a->ntest, Erv);
                                a->nbody = list1(n->right);                     // then goto l
-                               break;
-
-                       case Sfalse:
+                       } else if(arg == Strue) {
                                a = nod(OIF, N, N);
-                               a->ntest = nod(ONOT, n->left, N);       // if !val
-                               typecheck(&a->ntest, Erv);
+                               a->ntest = n->left;                     // if val
                                a->nbody = list1(n->right);                     // then goto l
-                               break;
-
-                       default:
-                       snorm:
+                       } else { // arg == Sfalse
                                a = nod(OIF, N, N);
-                               a->ntest = nod(OEQ, exprname, n->left); // if name == val
+                               a->ntest = nod(ONOT, n->left, N);       // if !val
                                typecheck(&a->ntest, Erv);
                                a->nbody = list1(n->right);                     // then goto l
-                               break;
                        }
 
                        cas = list(cas, a);
index c73c34804f85d49dffc86c7d491ea85733157333..649f1c5120b1c3e4b4093ccb38bc69d67a290ce9 100644 (file)
@@ -555,178 +555,7 @@ reswitch:
                if(l->type == T || r->type == T)
                        goto error;
                op = n->op;
-       arith:
-               if(op == OLSH || op == ORSH)
-                       goto shift;
-               // ideal mixed with non-ideal
-               defaultlit2(&l, &r, 0);
-               n->left = l;
-               n->right = r;
-               if(l->type == T || r->type == T)
-                       goto error;
-               t = l->type;
-               if(t->etype == TIDEAL)
-                       t = r->type;
-               et = t->etype;
-               if(et == TIDEAL)
-                       et = TINT;
-               aop = 0;
-               if(iscmp[n->op] && t->etype != TIDEAL && !eqtype(l->type, r->type)) {
-                       // comparison is okay as long as one side is
-                       // assignable to the other.  convert so they have
-                       // the same type.
-                       //
-                       // the only conversion that isn't a no-op is concrete == interface.
-                       // in that case, check comparability of the concrete type.
-                       // The conversion allocates, so only do it if the concrete type is huge.
-                       if(r->type->etype != TBLANK && (aop = assignop(l->type, r->type, nil)) != 0) {
-                               if(isinter(r->type) && !isinter(l->type) && algtype1(l->type, nil) == ANOEQ) {
-                                       yyerror("invalid operation: %N (operator %O not defined on %s)", n, op, typekind(l->type));
-                                       goto error;
-                               }
-                               dowidth(l->type);
-                               if(isinter(r->type) == isinter(l->type) || l->type->width >= 1<<16) {
-                                       l = nod(aop, l, N);
-                                       l->type = r->type;
-                                       l->typecheck = 1;
-                                       n->left = l;
-                               }
-                               t = r->type;
-                               goto converted;
-                       }
-                       if(l->type->etype != TBLANK && (aop = assignop(r->type, l->type, nil)) != 0) {
-                               if(isinter(l->type) && !isinter(r->type) && algtype1(r->type, nil) == ANOEQ) {
-                                       yyerror("invalid operation: %N (operator %O not defined on %s)", n, op, typekind(r->type));
-                                       goto error;
-                               }
-                               dowidth(r->type);
-                               if(isinter(r->type) == isinter(l->type) || r->type->width >= 1<<16) {
-                                       r = nod(aop, r, N);
-                                       r->type = l->type;
-                                       r->typecheck = 1;
-                                       n->right = r;
-                               }
-                               t = l->type;
-                       }
-               converted:
-                       et = t->etype;
-               }
-               if(t->etype != TIDEAL && !eqtype(l->type, r->type)) {
-                       defaultlit2(&l, &r, 1);
-                       if(n->op == OASOP && n->implicit) {
-                               yyerror("invalid operation: %N (non-numeric type %T)", n, l->type);
-                               goto error;
-                       }
-                       if(isinter(r->type) == isinter(l->type) || aop == 0) {
-                               yyerror("invalid operation: %N (mismatched types %T and %T)", n, l->type, r->type);
-                               goto error;
-                       }
-               }
-               if(!okfor[op][et]) {
-                       yyerror("invalid operation: %N (operator %O not defined on %s)", n, op, typekind(t));
-                       goto error;
-               }
-               // okfor allows any array == array, map == map, func == func.
-               // restrict to slice/map/func == nil and nil == slice/map/func.
-               if(isfixedarray(l->type) && algtype1(l->type, nil) == ANOEQ) {
-                       yyerror("invalid operation: %N (%T cannot be compared)", n, l->type);
-                       goto error;
-               }
-               if(isslice(l->type) && !isnil(l) && !isnil(r)) {
-                       yyerror("invalid operation: %N (slice can only be compared to nil)", n);
-                       goto error;
-               }
-               if(l->type->etype == TMAP && !isnil(l) && !isnil(r)) {
-                       yyerror("invalid operation: %N (map can only be compared to nil)", n);
-                       goto error;
-               }
-               if(l->type->etype == TFUNC && !isnil(l) && !isnil(r)) {
-                       yyerror("invalid operation: %N (func can only be compared to nil)", n);
-                       goto error;
-               }
-               if(l->type->etype == TSTRUCT && algtype1(l->type, &badtype) == ANOEQ) {
-                       yyerror("invalid operation: %N (struct containing %T cannot be compared)", n, badtype);
-                       goto error;
-               }
-               
-               t = l->type;
-               if(iscmp[n->op]) {
-                       evconst(n);
-                       t = idealbool;
-                       if(n->op != OLITERAL) {
-                               defaultlit2(&l, &r, 1);
-                               n->left = l;
-                               n->right = r;
-                       }
-               } else if(n->op == OANDAND || n->op == OOROR) {
-                       if(l->type == r->type)
-                               t = l->type;
-                       else if(l->type == idealbool)
-                               t = r->type;
-                       else if(r->type == idealbool)
-                               t = l->type;
-               // non-comparison operators on ideal bools should make them lose their ideal-ness
-               } else if(t == idealbool)
-                       t = types[TBOOL];
-
-               if(et == TSTRING) {
-                       if(iscmp[n->op]) {
-                               n->etype = n->op;
-                               n->op = OCMPSTR;
-                       } else if(n->op == OADD) {
-                               // create OADDSTR node with list of strings in x + y + z + (w + v) + ...
-                               n->op = OADDSTR;
-                               if(l->op == OADDSTR)
-                                       n->list = l->list;
-                               else
-                                       n->list = list1(l);
-                               if(r->op == OADDSTR)
-                                       n->list = concat(n->list, r->list);
-                               else
-                                       n->list = list(n->list, r);
-                               n->left = N;
-                               n->right = N;
-                       }
-               }
-               if(et == TINTER) {
-                       if(l->op == OLITERAL && l->val.ctype == CTNIL) {
-                               // swap for back end
-                               n->left = r;
-                               n->right = l;
-                       } else if(r->op == OLITERAL && r->val.ctype == CTNIL) {
-                               // leave alone for back end
-                       } else if(isinter(r->type) == isinter(l->type)) {
-                               n->etype = n->op;
-                               n->op = OCMPIFACE;
-                       }
-               }
-
-               if((op == ODIV || op == OMOD) && isconst(r, CTINT))
-               if(mpcmpfixc(r->val.u.xval, 0) == 0) {
-                       yyerror("division by zero");
-                       goto error;
-               } 
-
-               n->type = t;
-               goto ret;
-
-       shift:
-               defaultlit(&r, types[TUINT]);
-               n->right = r;
-               t = r->type;
-               if(!isint[t->etype] || issigned[t->etype]) {
-                       yyerror("invalid operation: %N (shift count type %T, must be unsigned integer)", n, r->type);
-                       goto error;
-               }
-               t = l->type;
-               if(t != T && t->etype != TIDEAL && !isint[t->etype]) {
-                       yyerror("invalid operation: %N (shift of type %T)", n, t);
-                       goto error;
-               }
-               // no defaultlit for left
-               // the outer context gives the type
-               n->type = l->type;
-               goto ret;
+               goto arith;
 
        case OCOM:
        case OMINUS:
@@ -1454,41 +1283,7 @@ reswitch:
                goto ret;
 
        case OCONV:
-       doconv:
-               ok |= Erv;
-               saveorignode(n);
-               typecheck(&n->left, Erv | (top & (Eindir | Eiota)));
-               convlit1(&n->left, n->type, 1);
-               if((t = n->left->type) == T || n->type == T)
-                       goto error;
-               if((n->op = convertop(t, n->type, &why)) == 0) {
-                       if(!n->diag && !n->type->broke) {
-                               yyerror("cannot convert %lN to type %T%s", n->left, n->type, why);
-                               n->diag = 1;
-                       }
-                       n->op = OCONV;
-               }
-               switch(n->op) {
-               case OCONVNOP:
-                       if(n->left->op == OLITERAL && n->type != types[TBOOL]) {
-                               r = nod(OXXX, N, N);
-                               n->op = OCONV;
-                               n->orig = r;
-                               *r = *n;
-                               n->op = OLITERAL;
-                               n->val = n->left->val;
-                       }
-                       break;
-               case OSTRARRAYBYTE:
-                       // do not use stringtoarraylit.
-                       // generated code and compiler memory footprint is better without it.
-                       break;
-               case OSTRARRAYRUNE:
-                       if(n->left->op == OLITERAL)
-                               stringtoarraylit(&n);
-                       break;
-               }
-               goto ret;
+               goto doconv;
 
        case OMAKE:
                ok |= Erv;
@@ -1506,13 +1301,14 @@ reswitch:
 
                switch(t->etype) {
                default:
-               badmake:
                        yyerror("cannot make type %T", t);
                        goto error;
 
                case TARRAY:
-                       if(!isslice(t))
-                               goto badmake;
+                       if(!isslice(t)) {
+                               yyerror("cannot make type %T", t);
+                               goto error;
+                       }
                        if(args == nil) {
                                yyerror("missing len argument to make(%T)", t);
                                goto error;
@@ -1805,6 +1601,216 @@ reswitch:
                        checkwidth(n->left->type);
                goto ret;
        }
+       goto ret;
+
+arith:
+       if(op == OLSH || op == ORSH)
+               goto shift;
+       // ideal mixed with non-ideal
+       defaultlit2(&l, &r, 0);
+       n->left = l;
+       n->right = r;
+       if(l->type == T || r->type == T)
+               goto error;
+       t = l->type;
+       if(t->etype == TIDEAL)
+               t = r->type;
+       et = t->etype;
+       if(et == TIDEAL)
+               et = TINT;
+       aop = 0;
+       if(iscmp[n->op] && t->etype != TIDEAL && !eqtype(l->type, r->type)) {
+               // comparison is okay as long as one side is
+               // assignable to the other.  convert so they have
+               // the same type.
+               //
+               // the only conversion that isn't a no-op is concrete == interface.
+               // in that case, check comparability of the concrete type.
+               // The conversion allocates, so only do it if the concrete type is huge.
+               if(r->type->etype != TBLANK && (aop = assignop(l->type, r->type, nil)) != 0) {
+                       if(isinter(r->type) && !isinter(l->type) && algtype1(l->type, nil) == ANOEQ) {
+                               yyerror("invalid operation: %N (operator %O not defined on %s)", n, op, typekind(l->type));
+                               goto error;
+                       }
+                       dowidth(l->type);
+                       if(isinter(r->type) == isinter(l->type) || l->type->width >= 1<<16) {
+                               l = nod(aop, l, N);
+                               l->type = r->type;
+                               l->typecheck = 1;
+                               n->left = l;
+                       }
+                       t = r->type;
+                       goto converted;
+               }
+               if(l->type->etype != TBLANK && (aop = assignop(r->type, l->type, nil)) != 0) {
+                       if(isinter(l->type) && !isinter(r->type) && algtype1(r->type, nil) == ANOEQ) {
+                               yyerror("invalid operation: %N (operator %O not defined on %s)", n, op, typekind(r->type));
+                               goto error;
+                       }
+                       dowidth(r->type);
+                       if(isinter(r->type) == isinter(l->type) || r->type->width >= 1<<16) {
+                               r = nod(aop, r, N);
+                               r->type = l->type;
+                               r->typecheck = 1;
+                               n->right = r;
+                       }
+                       t = l->type;
+               }
+       converted:
+               et = t->etype;
+       }
+       if(t->etype != TIDEAL && !eqtype(l->type, r->type)) {
+               defaultlit2(&l, &r, 1);
+               if(n->op == OASOP && n->implicit) {
+                       yyerror("invalid operation: %N (non-numeric type %T)", n, l->type);
+                       goto error;
+               }
+               if(isinter(r->type) == isinter(l->type) || aop == 0) {
+                       yyerror("invalid operation: %N (mismatched types %T and %T)", n, l->type, r->type);
+                       goto error;
+               }
+       }
+       if(!okfor[op][et]) {
+               yyerror("invalid operation: %N (operator %O not defined on %s)", n, op, typekind(t));
+               goto error;
+       }
+       // okfor allows any array == array, map == map, func == func.
+       // restrict to slice/map/func == nil and nil == slice/map/func.
+       if(isfixedarray(l->type) && algtype1(l->type, nil) == ANOEQ) {
+               yyerror("invalid operation: %N (%T cannot be compared)", n, l->type);
+               goto error;
+       }
+       if(isslice(l->type) && !isnil(l) && !isnil(r)) {
+               yyerror("invalid operation: %N (slice can only be compared to nil)", n);
+               goto error;
+       }
+       if(l->type->etype == TMAP && !isnil(l) && !isnil(r)) {
+               yyerror("invalid operation: %N (map can only be compared to nil)", n);
+               goto error;
+       }
+       if(l->type->etype == TFUNC && !isnil(l) && !isnil(r)) {
+               yyerror("invalid operation: %N (func can only be compared to nil)", n);
+               goto error;
+       }
+       if(l->type->etype == TSTRUCT && algtype1(l->type, &badtype) == ANOEQ) {
+               yyerror("invalid operation: %N (struct containing %T cannot be compared)", n, badtype);
+               goto error;
+       }
+       
+       t = l->type;
+       if(iscmp[n->op]) {
+               evconst(n);
+               t = idealbool;
+               if(n->op != OLITERAL) {
+                       defaultlit2(&l, &r, 1);
+                       n->left = l;
+                       n->right = r;
+               }
+       } else if(n->op == OANDAND || n->op == OOROR) {
+               if(l->type == r->type)
+                       t = l->type;
+               else if(l->type == idealbool)
+                       t = r->type;
+               else if(r->type == idealbool)
+                       t = l->type;
+       // non-comparison operators on ideal bools should make them lose their ideal-ness
+       } else if(t == idealbool)
+               t = types[TBOOL];
+
+       if(et == TSTRING) {
+               if(iscmp[n->op]) {
+                       n->etype = n->op;
+                       n->op = OCMPSTR;
+               } else if(n->op == OADD) {
+                       // create OADDSTR node with list of strings in x + y + z + (w + v) + ...
+                       n->op = OADDSTR;
+                       if(l->op == OADDSTR)
+                               n->list = l->list;
+                       else
+                               n->list = list1(l);
+                       if(r->op == OADDSTR)
+                               n->list = concat(n->list, r->list);
+                       else
+                               n->list = list(n->list, r);
+                       n->left = N;
+                       n->right = N;
+               }
+       }
+       if(et == TINTER) {
+               if(l->op == OLITERAL && l->val.ctype == CTNIL) {
+                       // swap for back end
+                       n->left = r;
+                       n->right = l;
+               } else if(r->op == OLITERAL && r->val.ctype == CTNIL) {
+                       // leave alone for back end
+               } else if(isinter(r->type) == isinter(l->type)) {
+                       n->etype = n->op;
+                       n->op = OCMPIFACE;
+               }
+       }
+
+       if((op == ODIV || op == OMOD) && isconst(r, CTINT))
+       if(mpcmpfixc(r->val.u.xval, 0) == 0) {
+               yyerror("division by zero");
+               goto error;
+       } 
+
+       n->type = t;
+       goto ret;
+
+shift:
+       defaultlit(&r, types[TUINT]);
+       n->right = r;
+       t = r->type;
+       if(!isint[t->etype] || issigned[t->etype]) {
+               yyerror("invalid operation: %N (shift count type %T, must be unsigned integer)", n, r->type);
+               goto error;
+       }
+       t = l->type;
+       if(t != T && t->etype != TIDEAL && !isint[t->etype]) {
+               yyerror("invalid operation: %N (shift of type %T)", n, t);
+               goto error;
+       }
+       // no defaultlit for left
+       // the outer context gives the type
+       n->type = l->type;
+       goto ret;
+
+doconv:
+       ok |= Erv;
+       saveorignode(n);
+       typecheck(&n->left, Erv | (top & (Eindir | Eiota)));
+       convlit1(&n->left, n->type, 1);
+       if((t = n->left->type) == T || n->type == T)
+               goto error;
+       if((n->op = convertop(t, n->type, &why)) == 0) {
+               if(!n->diag && !n->type->broke) {
+                       yyerror("cannot convert %lN to type %T%s", n->left, n->type, why);
+                       n->diag = 1;
+               }
+               n->op = OCONV;
+       }
+       switch(n->op) {
+       case OCONVNOP:
+               if(n->left->op == OLITERAL && n->type != types[TBOOL]) {
+                       r = nod(OXXX, N, N);
+                       n->op = OCONV;
+                       n->orig = r;
+                       *r = *n;
+                       n->op = OLITERAL;
+                       n->val = n->left->val;
+               }
+               break;
+       case OSTRARRAYBYTE:
+               // do not use stringtoarraylit.
+               // generated code and compiler memory footprint is better without it.
+               break;
+       case OSTRARRAYRUNE:
+               if(n->left->op == OLITERAL)
+                       stringtoarraylit(&n);
+               break;
+       }
+       goto ret;
 
 ret:
        t = n->type;
@@ -1925,7 +1931,7 @@ checkdefergo(Node *n)
        case OPRINTN:
        case ORECOVER:
                // ok
-               break;
+               return;
        case OAPPEND:
        case OCAP:
        case OCOMPLEX:
@@ -1939,23 +1945,21 @@ checkdefergo(Node *n)
        case OREAL:
        case OLITERAL: // conversion or unsafe.Alignof, Offsetof, Sizeof
                if(n->left->orig != N && n->left->orig->op == OCONV)
-                       goto conv;
-               yyerror("%s discards result of %N", what, n->left);
-               break;
-       default:
-       conv:
-               // type is broken or missing, most likely a method call on a broken type
-               // we will warn about the broken type elsewhere. no need to emit a potentially confusing error
-               if(n->left->type == T || n->left->type->broke)
                        break;
+               yyerror("%s discards result of %N", what, n->left);
+               return;
+       }
 
-               if(!n->diag) {
-                       // The syntax made sure it was a call, so this must be
-                       // a conversion.
-                       n->diag = 1;
-                       yyerror("%s requires function call, not conversion", what);
-               }
-               break;
+       // type is broken or missing, most likely a method call on a broken type
+       // we will warn about the broken type elsewhere. no need to emit a potentially confusing error
+       if(n->left->type == T || n->left->type->broke)
+               return;
+
+       if(!n->diag) {
+               // The syntax made sure it was a call, so this must be
+               // a conversion.
+               n->diag = 1;
+               yyerror("%s requires function call, not conversion", what);
        }
 }
 
@@ -3048,15 +3052,20 @@ typecheckas2(Node *n)
                        goto out;
                switch(r->op) {
                case OINDEXMAP:
-                       n->op = OAS2MAPR;
-                       goto common;
                case ORECV:
-                       n->op = OAS2RECV;
-                       goto common;
                case ODOTTYPE:
-                       n->op = OAS2DOTTYPE;
-                       r->op = ODOTTYPE2;
-               common:
+                       switch(r->op) {
+                       case OINDEXMAP:
+                               n->op = OAS2MAPR;
+                               break;
+                       case ORECV:
+                               n->op = OAS2RECV;
+                               break;
+                       case ODOTTYPE:
+                               n->op = OAS2DOTTYPE;
+                               r->op = ODOTTYPE2;
+                               break;
+                       }
                        if(l->type != T)
                                checkassignto(r->type, l);
                        if(l->defn == n)