tfn.Rlist.Append(n)
 
        funchdr(fn)
-       typecheck(&fn.Func.Nname.Name.Param.Ntype, Etype)
+       fn.Func.Nname.Name.Param.Ntype = typecheck(fn.Func.Nname.Name.Param.Ntype, Etype)
 
        // genhash is only called for types that have equality but
        // cannot be handled by the standard algorithms,
        funcbody(fn)
        Curfn = fn
        fn.Func.Dupok = true
-       typecheck(&fn, Etop)
+       fn = typecheck(fn, Etop)
        typecheckslice(fn.Nbody.Slice(), Etop)
        Curfn = nil
        popdcl()
        tfn.List.Append(Nod(ODCLFIELD, nil, typenod(Ptrto(t))))
        tfn.List.Append(Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
        tfn.Rlist.Append(Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
-       typecheck(&tfn, Etype)
+       tfn = typecheck(tfn, Etype)
        n.Type = tfn.Type
        return n
 }
        tfn.Rlist.Append(n)
 
        funchdr(fn)
-       typecheck(&fn.Func.Nname.Name.Param.Ntype, Etype)
+       fn.Func.Nname.Name.Param.Ntype = typecheck(fn.Func.Nname.Name.Param.Ntype, Etype)
 
        // geneq is only called for types that have equality but
        // cannot be handled by the standard algorithms,
        funcbody(fn)
        Curfn = fn
        fn.Func.Dupok = true
-       typecheck(&fn, Etop)
+       fn = typecheck(fn, Etop)
        typecheckslice(fn.Nbody.Slice(), Etop)
        Curfn = nil
        popdcl()
        nx.Etype = 1 // does not escape
        ny := Nod(OADDR, NodSym(OXDOT, q, field), nil)
        ny.Etype = 1 // does not escape
-       typecheck(&nx, Erv)
-       typecheck(&ny, Erv)
+       nx = typecheck(nx, Erv)
+       ny = typecheck(ny, Erv)
 
        fn, needsize := eqmemfunc(size, nx.Type.Type)
        call := Nod(OCALL, fn, nil)
                fn = syslook(buf)
        }
 
-       substArgTypes(&fn, t, t)
+       fn = substArgTypes(fn, t, t)
        return fn, needsize
 }
 
 
                        switch n := sym.Def; n.Op {
                        case OLITERAL:
                                // constant
-                               typecheck(&n, Erv)
+                               n = typecheck(n, Erv)
                                if n == nil || n.Op != OLITERAL {
                                        Fatalf("exporter: dumpexportconst: oconst nil: %v", sym)
                                }
 
                        case ONAME:
                                // variable or function
-                               typecheck(&n, Erv|Ecall)
+                               n = typecheck(n, Erv|Ecall)
                                if n == nil || n.Type == nil {
                                        Fatalf("exporter: variable/function exported but not defined: %v", sym)
                                }
 
        case OMINUS:
                if Isfloat[nl.Type.Etype] {
                        nr = Nodintconst(-1)
-                       convlit(&nr, n.Type)
+                       nr = convlit(nr, n.Type)
                        a = Thearch.Optoas(OMUL, nl.Type)
                        goto sbop
                }
 
        wbVar := syslook("writeBarrier")
        wbEnabled := NodSym(ODOT, wbVar, wbVar.Type.Field(0).Sym)
-       wbEnabled = typecheck(&wbEnabled, Erv)
+       wbEnabled = typecheck(wbEnabled, Erv)
        pbr := Thearch.Ginscmp(ONE, Types[TUINT8], wbEnabled, Nodintconst(0), -1)
        Thearch.Gins(Thearch.Optoas(OAS, Types[Tptr]), &src, &dst)
        pjmp := Gbranch(obj.AJMP, nil, 0)
        Genlist(n.Ninit)
 
        if n.Type == nil {
-               convlit(&n, Types[TBOOL])
+               n = convlit(n, Types[TBOOL])
                if n.Type == nil {
                        return
                }
        Regfree(&rlen)
 
        fn := syslook("growslice")
-       substArgTypes(&fn, res.Type.Type, res.Type.Type)
+       fn = substArgTypes(fn, res.Type.Type, res.Type.Type)
        Ginscall(fn, 0)
 
        if Widthptr == 4 && Widthreg == 8 {
 
        }
 
        oldfn := Curfn
-       typecheck(&func_.Func.Ntype, Etype)
+       func_.Func.Ntype = typecheck(func_.Func.Ntype, Etype)
        func_.Type = func_.Func.Ntype.Type
        func_.Func.Top = top
 
        if len(xfunc.Nbody.Slice()) == 0 {
                Fatalf("empty body - won't generate any code")
        }
-       typecheck(&xfunc, Etop)
+       xfunc = typecheck(xfunc, Etop)
 
        xfunc.Func.Closure = func_
        func_.Func.Closure = xfunc
                        Warnl(v.Lineno, "%v capturing by %s: %v (addr=%v assign=%v width=%d)", name, how, v.Sym, v.Name.Param.Closure.Addrtaken, v.Name.Param.Closure.Assigned, int32(v.Type.Width))
                }
 
-               typecheck(&outer, Erv)
+               outer = typecheck(outer, Erv)
                func_.Func.Enter.Append(outer)
        }
 
 
        clos.Type = func_.Type
 
-       typecheck(&clos, Erv)
+       clos = typecheck(clos, Erv)
 
        // typecheck will insert a PTRLIT node under CONVNOP,
        // tag it with escape analysis result.
                delete(prealloc, func_)
        }
 
-       walkexpr(&clos, init)
+       clos = walkexpr(clos, init)
 
        return clos
 }
 
        xfunc.Nbody.Set(body)
 
-       typecheck(&xfunc, Etop)
+       xfunc = typecheck(xfunc, Etop)
        sym.Def = xfunc
        xtop = append(xtop, xfunc)
        Curfn = savecurfn
 
        clos.Type = n.Type
 
-       typecheck(&clos, Erv)
+       clos = typecheck(clos, Erv)
 
        // typecheck will insert a PTRLIT node under CONVNOP,
        // tag it with escape analysis result.
                delete(prealloc, n)
        }
 
-       walkexpr(&clos, init)
+       clos = walkexpr(clos, init)
 
        return clos
 }
 
 // NegOne returns a Node of type t with value -1.
 func NegOne(t *Type) *Node {
        n := Nodintconst(-1)
-       convlit(&n, t)
+       n = convlit(n, t)
        return n
 }
 
 // convert n, if literal, to type t.
 // implicit conversion.
-func convlit(np **Node, t *Type) {
-       convlit1(np, t, false)
+// The result of convlit MUST be assigned back to n, e.g.
+//     n.Left = convlit(n.Left, t)
+func convlit(n *Node, t *Type) *Node {
+       return convlit1(n, t, false)
 }
 
 // convert n, if literal, to type t.
 // return a new node if necessary
-//(if n is a named constant, can't edit n->type directly).
-func convlit1(np **Node, t *Type, explicit bool) {
-       n := *np
+// (if n is a named constant, can't edit n->type directly).
+// The result of convlit1 MUST be assigned back to n, e.g.
+//     n.Left = convlit1(n.Left, t, explicit)
+func convlit1(n *Node, t *Type, explicit bool) *Node {
        if n == nil || t == nil || n.Type == nil || isideal(t) || n.Type == t {
-               return
+               return n
        }
        if !explicit && !isideal(n.Type) {
-               return
+               return n
        }
 
        if n.Op == OLITERAL {
                nn := Nod(OXXX, nil, nil)
                *nn = *n
                n = nn
-               *np = n
        }
 
        switch n.Op {
                }
 
                if n.Type.Etype == TIDEAL {
-                       convlit(&n.Left, t)
-                       convlit(&n.Right, t)
+                       n.Left = convlit(n.Left, t)
+                       n.Right = convlit(n.Right, t)
                        n.Type = t
                }
 
-               return
+               return n
 
                // target is invalid type for a constant?  leave alone.
        case OLITERAL:
                if !okforconst[t.Etype] && n.Type.Etype != TNIL {
-                       defaultlit(&n, nil)
-                       *np = n
-                       return
+                       n = defaultlit(n, nil)
+                       return n
                }
 
        case OLSH, ORSH:
-               convlit1(&n.Left, t, explicit && isideal(n.Left.Type))
+               n.Left = convlit1(n.Left, t, explicit && isideal(n.Left.Type))
                t = n.Left.Type
                if t != nil && t.Etype == TIDEAL && n.Val().Ctype() != CTINT {
                        n.SetVal(toint(n.Val()))
                }
 
                n.Type = t
-               return
+               return n
 
        case OCOMPLEX:
                if n.Type.Etype == TIDEAL {
                        case TCOMPLEX128:
                                n.Type = t
 
-                               convlit(&n.Left, Types[TFLOAT64])
-                               convlit(&n.Right, Types[TFLOAT64])
+                               n.Left = convlit(n.Left, Types[TFLOAT64])
+                               n.Right = convlit(n.Right, Types[TFLOAT64])
 
                        case TCOMPLEX64:
                                n.Type = t
-                               convlit(&n.Left, Types[TFLOAT32])
-                               convlit(&n.Right, Types[TFLOAT32])
+                               n.Left = convlit(n.Left, Types[TFLOAT32])
+                               n.Right = convlit(n.Right, Types[TFLOAT32])
                        }
                }
 
-               return
+               return n
        }
 
        // avoided repeated calculations, errors
        if Eqtype(n.Type, t) {
-               return
+               return n
        }
 
        ct := consttype(n)
        if et == TINTER {
                if ct == CTNIL && n.Type == Types[TNIL] {
                        n.Type = t
-                       return
+                       return n
                }
 
-               defaultlit(np, nil)
-               return
+               n = defaultlit(n, nil)
+               return n
        }
 
        switch ct {
 
                        // let normal conversion code handle it
                case TSTRING:
-                       return
+                       return n
 
                case TARRAY:
                        if !Isslice(t) {
        }
 
        n.Type = t
-       return
+       return n
 
 bad:
        if n.Diag == 0 {
        }
 
        if isideal(n.Type) {
-               defaultlit(&n, nil)
-               *np = n
+               n = defaultlit(n, nil)
        }
+       return n
 }
 
 func copyval(v Val) Val {
                        OCONV_ | CTFLT_,
                        OCONV_ | CTSTR_,
                        OCONV_ | CTBOOL_:
-                       convlit1(&nl, n.Type, true)
+                       nl = convlit1(nl, n.Type, true)
 
                        v = nl.Val()
 
        // ideal const mixes with anything but otherwise must match.
        default:
                if nl.Type.Etype != TIDEAL {
-                       defaultlit(&nr, nl.Type)
+                       nr = defaultlit(nr, nl.Type)
                        n.Right = nr
                }
 
                if nr.Type.Etype != TIDEAL {
-                       defaultlit(&nl, nr.Type)
+                       nl = defaultlit(nl, nr.Type)
                        n.Left = nl
                }
 
                // right must be unsigned.
        // left can be ideal.
        case OLSH, ORSH:
-               defaultlit(&nr, Types[TUINT])
+               nr = defaultlit(nr, Types[TUINT])
 
                n.Right = nr
                if nr.Type != nil && (Issigned[nr.Type.Etype] || !Isint[nr.Type.Etype]) {
        }
 }
 
-func defaultlit(np **Node, t *Type) {
-       n := *np
+// The result of defaultlit MUST be assigned back to n, e.g.
+//     n.Left = defaultlit(n.Left, t)
+func defaultlit(n *Node, t *Type) *Node {
        if n == nil || !isideal(n.Type) {
-               return
+               return n
        }
 
        if n.Op == OLITERAL {
                nn := Nod(OXXX, nil, nil)
                *nn = *n
                n = nn
-               *np = n
        }
 
        lno := setlineno(n)
        switch ctype {
        default:
                if t != nil {
-                       convlit(np, t)
-                       return
+                       n = convlit(n, t)
+                       return n
                }
 
                if n.Val().Ctype() == CTNIL {
 
                if n.Val().Ctype() == CTSTR {
                        t1 := Types[TSTRING]
-                       convlit(np, t1)
+                       n = convlit(n, t1)
                        break
                }
 
                if t != nil && t.Etype == TBOOL {
                        t1 = t
                }
-               convlit(np, t1)
+               n = convlit(n, t1)
 
        case CTINT:
                t1 = Types[TINT]
        }
 
        lineno = lno
-       return
+       return n
 
 num:
        // Note: n.Val().Ctype() can be CTxxx (not a constant) here
        if n.Val().Ctype() != CTxxx {
                overflow(n.Val(), t1)
        }
-       convlit(np, t1)
+       n = convlit(n, t1)
        lineno = lno
-       return
+       return n
 }
 
 // defaultlit on both nodes simultaneously;
 // if they're both ideal going in they better
 // get the same type going out.
 // force means must assign concrete (non-ideal) type.
-func defaultlit2(lp **Node, rp **Node, force bool) {
-       l := *lp
-       r := *rp
+// The results of defaultlit2 MUST be assigned back to l and r, e.g.
+//     n.Left, n.Right = defaultlit2(n.Left, n.Right, force)
+func defaultlit2(l *Node, r *Node, force bool) (*Node, *Node) {
        if l.Type == nil || r.Type == nil {
-               return
+               return l, r
        }
        if !isideal(l.Type) {
-               convlit(rp, l.Type)
-               return
+               r = convlit(r, l.Type)
+               return l, r
        }
 
        if !isideal(r.Type) {
-               convlit(lp, r.Type)
-               return
+               l = convlit(l, r.Type)
+               return l, r
        }
 
        if !force {
-               return
+               return l, r
        }
 
        if l.Type.Etype == TBOOL {
-               convlit(lp, Types[TBOOL])
-               convlit(rp, Types[TBOOL])
+               l = convlit(l, Types[TBOOL])
+               r = convlit(r, Types[TBOOL])
        }
 
        lkind := idealkind(l)
        rkind := idealkind(r)
        if lkind == CTCPLX || rkind == CTCPLX {
-               convlit(lp, Types[TCOMPLEX128])
-               convlit(rp, Types[TCOMPLEX128])
-               return
+               l = convlit(l, Types[TCOMPLEX128])
+               r = convlit(r, Types[TCOMPLEX128])
+               return l, r
        }
 
        if lkind == CTFLT || rkind == CTFLT {
-               convlit(lp, Types[TFLOAT64])
-               convlit(rp, Types[TFLOAT64])
-               return
+               l = convlit(l, Types[TFLOAT64])
+               r = convlit(r, Types[TFLOAT64])
+               return l, r
        }
 
        if lkind == CTRUNE || rkind == CTRUNE {
-               convlit(lp, runetype)
-               convlit(rp, runetype)
-               return
+               l = convlit(l, runetype)
+               r = convlit(r, runetype)
+               return l, r
        }
 
-       convlit(lp, Types[TINT])
-       convlit(rp, Types[TINT])
+       l = convlit(l, Types[TINT])
+       r = convlit(r, Types[TINT])
+
+       return l, r
 }
 
 // strlit returns the value of a literal string Node as a string.
 
        f.Isddd = n.Isddd
 
        if n.Right != nil {
-               typecheck(&n.Right, Etype)
+               n.Right = typecheck(n.Right, Etype)
                n.Type = n.Right.Type
                if n.Left != nil {
                        n.Left.Type = n.Type
                                f.Sym = f.Nname.Sym
                        }
                } else {
-                       typecheck(&n.Right, Etype)
+                       n.Right = typecheck(n.Right, Etype)
                        n.Type = n.Right.Type
 
                        if n.Embedded != 0 {
 
                                a = Nod(OADDR, a, nil)
                                a.Lineno = v.Lineno
                                e.nodeEscState(a).Escloopdepth = e.loopdepth
-                               typecheck(&a, Erv)
+                               a = typecheck(a, Erv)
                        }
 
                        escassignNilWhy(e, n, a, "captured by a closure")
 
 
 func dumpexportconst(s *Sym) {
        n := s.Def
-       typecheck(&n, Erv)
+       n = typecheck(n, Erv)
        if n == nil || n.Op != OLITERAL {
                Fatalf("dumpexportconst: oconst nil: %v", s)
        }
 
 func dumpexportvar(s *Sym) {
        n := s.Def
-       typecheck(&n, Erv|Ecall)
+       n = typecheck(n, Erv|Ecall)
        if n == nil || n.Type == nil {
                Yyerror("variable exported but not defined: %v", s)
                return
 
 func importconst(s *Sym, t *Type, n *Node) {
        importsym(s, OLITERAL)
-       convlit(&n, t)
+       n = convlit(n, t)
 
        if s.Def != nil { // TODO: check if already the same.
                return
 
        funcbody(fn)
 
        Curfn = fn
-       typecheck(&fn, Etop)
+       fn = typecheck(fn, Etop)
        typecheckslice(r, Etop)
        Curfn = nil
        funccompile(fn)
 
 func inlcalls(fn *Node) {
        savefn := Curfn
        Curfn = fn
-       inlnode(&fn)
+       fn = inlnode(fn)
        if fn != Curfn {
                Fatalf("inlnode replaced curfn")
        }
 }
 
 // Turn an OINLCALL into a single valued expression.
-func inlconv2expr(np **Node) {
-       n := *np
+// The result of inlconv2expr MUST be assigned back to n, e.g.
+//     n.Left = inlconv2expr(n.Left)
+func inlconv2expr(n *Node) *Node {
        r := n.Rlist.First()
-       addinit(&r, append(n.Ninit.Slice(), n.Nbody.Slice()...))
-       *np = r
+       r = addinit(r, append(n.Ninit.Slice(), n.Nbody.Slice()...))
+       return r
 }
 
 // Turn the rlist (with the return values) of the OINLCALL in
        }
 
        s := n.Rlist.Slice()
-       addinit(&s[0], append(n.Ninit.Slice(), n.Nbody.Slice()...))
+       s[0] = addinit(s[0], append(n.Ninit.Slice(), n.Nbody.Slice()...))
        return s
 }
 
 func inlnodelist(l Nodes) {
        s := l.Slice()
        for i := range s {
-               inlnode(&s[i])
+               s[i] = inlnode(s[i])
        }
 }
 
 // have to edit /this/ n, so you'd have to push that one down as well,
 // but then you may as well do it here.  so this is cleaner and
 // shorter and less complicated.
-func inlnode(np **Node) {
-       if *np == nil {
-               return
+// The result of inlnode MUST be assigned back to n, e.g.
+//     n.Left = inlnode(n.Left)
+func inlnode(n *Node) *Node {
+       if n == nil {
+               return n
        }
 
-       n := *np
-
        switch n.Op {
        // inhibit inlining of their argument
        case ODEFER, OPROC:
                // TODO do them here (or earlier),
        // so escape analysis can avoid more heapmoves.
        case OCLOSURE:
-               return
+               return n
        }
 
        lno := setlineno(n)
                }
        }
 
-       inlnode(&n.Left)
+       n.Left = inlnode(n.Left)
        if n.Left != nil && n.Left.Op == OINLCALL {
-               inlconv2expr(&n.Left)
+               n.Left = inlconv2expr(n.Left)
        }
 
-       inlnode(&n.Right)
+       n.Right = inlnode(n.Right)
        if n.Right != nil && n.Right.Op == OINLCALL {
                if n.Op == OFOR {
                        inlconv2stmt(n.Right)
                } else {
-                       inlconv2expr(&n.Right)
+                       n.Right = inlconv2expr(n.Right)
                }
        }
 
                s := n.List.Slice()
                for i1, n1 := range s {
                        if n1.Op == OINLCALL {
-                               inlconv2expr(&s[i1])
+                               s[i1] = inlconv2expr(s[i1])
                        }
                }
        }
                        n.Rlist.Set(inlconv2list(n.Rlist.First()))
                        n.Op = OAS2
                        n.Typecheck = 0
-                       typecheck(np, Etop)
+                       n = typecheck(n, Etop)
                        break
                }
                fallthrough
                                if n.Op == OIF {
                                        inlconv2stmt(n1)
                                } else {
-                                       inlconv2expr(&s[i1])
+                                       s[i1] = inlconv2expr(s[i1])
                                }
                        }
                }
        case OCALLFUNC, OCALLMETH:
                // TODO(marvin): Fix Node.EType type union.
                if n.Etype == EType(OPROC) || n.Etype == EType(ODEFER) {
-                       return
+                       return n
                }
        }
 
                        fmt.Printf("%v:call to func %v\n", n.Line(), Nconv(n.Left, FmtSign))
                }
                if n.Left.Func != nil && len(n.Left.Func.Inl.Slice()) != 0 { // normal case
-                       mkinlcall(np, n.Left, n.Isddd)
+                       n = mkinlcall(n, n.Left, n.Isddd)
                } else if n.Left.Op == ONAME && n.Left.Left != nil && n.Left.Left.Op == OTYPE && n.Left.Right != nil && n.Left.Right.Op == ONAME { // methods called as functions
                        if n.Left.Sym.Def != nil {
-                               mkinlcall(np, n.Left.Sym.Def, n.Isddd)
+                               n = mkinlcall(n, n.Left.Sym.Def, n.Isddd)
                        }
                }
 
                        Fatalf("no function definition for [%p] %v\n", n.Left.Type, Tconv(n.Left.Type, FmtSign))
                }
 
-               mkinlcall(np, n.Left.Type.Nname, n.Isddd)
+               n = mkinlcall(n, n.Left.Type.Nname, n.Isddd)
        }
 
        lineno = lno
+       return n
 }
 
-func mkinlcall(np **Node, fn *Node, isddd bool) {
+// The result of mkinlcall MUST be assigned back to n, e.g.
+//     n.Left = mkinlcall(n.Left, fn, isddd)
+func mkinlcall(n *Node, fn *Node, isddd bool) *Node {
        save_safemode := safemode
 
        // imported functions may refer to unsafe as long as the
        if pkg != localpkg && pkg != nil {
                safemode = 0
        }
-       mkinlcall1(np, fn, isddd)
+       n = mkinlcall1(n, fn, isddd)
        safemode = save_safemode
+       return n
 }
 
 func tinlvar(t *Field) *Node {
                return t.Nname.Name.Inlvar
        }
 
-       typecheck(&nblank, Erv|Easgn)
+       nblank = typecheck(nblank, Erv|Easgn)
        return nblank
 }
 
 // On return ninit has the parameter assignments, the nbody is the
 // inlined function body and list, rlist contain the input, output
 // parameters.
-func mkinlcall1(np **Node, fn *Node, isddd bool) {
+// The result of mkinlcall1 MUST be assigned back to n, e.g.
+//     n.Left = mkinlcall1(n.Left, fn, isddd)
+func mkinlcall1(n *Node, fn *Node, isddd bool) *Node {
        // For variadic fn.
        if len(fn.Func.Inl.Slice()) == 0 {
-               return
+               return n
        }
 
        if fn == Curfn || fn.Name.Defn == Curfn {
-               return
+               return n
        }
 
        if Debug['l'] < 2 {
                typecheckinl(fn)
        }
 
-       n := *np
-
        // Bingo, we have a function node, and it has an inlineable body
        if Debug['m'] > 1 {
                fmt.Printf("%v: inlining call to %v %v { %v }\n", n.Line(), fn.Sym, Tconv(fn.Type, FmtSharp), Hconv(fn.Func.Inl, FmtSharp))
                        ln.Name.Inlvar = inlvar(ln)
 
                        // Typecheck because inlvar is not necessarily a function parameter.
-                       typecheck(&ln.Name.Inlvar, Erv)
+                       ln.Name.Inlvar = typecheck(ln.Name.Inlvar, Erv)
 
                        if ln.Class&^PHEAP != PAUTO {
                                ninit.Append(Nod(ODCL, ln.Name.Inlvar, nil)) // otherwise gen won't emit the allocations for heapallocs
        for _, t := range fn.Type.Results().Fields().Slice() {
                if t != nil && t.Nname != nil && !isblank(t.Nname) {
                        m = inlvar(t.Nname)
-                       typecheck(&m, Erv)
+                       m = typecheck(m, Erv)
                        t.Nname.Name.Inlvar = m
                } else {
                        // anonymous return values, synthesize names for use in assignment that replaces return
                }
                as := Nod(OAS, tinlvar(t), n.Left.Left)
                if as != nil {
-                       typecheck(&as, Etop)
+                       as = typecheck(as, Etop)
                        ninit.Append(as)
                }
        }
        }
 
        if as.Rlist.Len() != 0 {
-               typecheck(&as, Etop)
+               as = typecheck(as, Etop)
                ninit.Append(as)
        }
 
                        as.Right = Nod(OSLICE, as.Right, Nod(OKEY, nil, nil))
                }
 
-               typecheck(&as, Etop)
+               as = typecheck(as, Etop)
                ninit.Append(as)
        }
 
        // zero the outparams
        for _, n := range retvars {
                as = Nod(OAS, n, nil)
-               typecheck(&as, Etop)
+               as = typecheck(as, Etop)
                ninit.Append(as)
        }
 
 
        //dumplist("call body", body);
 
-       *np = call
+       n = call
 
        // transitive inlining
        // might be nice to do this before exporting the body,
        fn.Func.Inl.Set(body)
 
        if Debug['m'] > 2 {
-               fmt.Printf("%v: After inlining %v\n\n", n.Line(), Nconv(*np, FmtSign))
+               fmt.Printf("%v: After inlining %v\n\n", n.Line(), Nconv(n, FmtSign))
        }
+
+       return n
 }
 
 // Every time we expand a function we generate a new set of tmpnames,
                                as.List.Append(n)
                        }
                        as.Rlist.Set(subst.list(n.List))
-                       typecheck(&as, Etop)
+                       as = typecheck(as, Etop)
                        m.Ninit.Append(as)
                }
 
                typecheckslice(m.Ninit.Slice(), Etop)
-               typecheck(&m, Etop)
+               m = typecheck(m, Etop)
 
                //              dump("Return after substitution", m);
                return m
 
        // Don't use range--typecheck can add closures to xtop.
        for i := 0; i < len(xtop); i++ {
                if xtop[i].Op != ODCL && xtop[i].Op != OAS && xtop[i].Op != OAS2 {
-                       typecheck(&xtop[i], Etop)
+                       xtop[i] = typecheck(xtop[i], Etop)
                }
        }
 
        // Don't use range--typecheck can add closures to xtop.
        for i := 0; i < len(xtop); i++ {
                if xtop[i].Op == ODCL || xtop[i].Op == OAS || xtop[i].Op == OAS2 {
-                       typecheck(&xtop[i], Etop)
+                       xtop[i] = typecheck(xtop[i], Etop)
                }
        }
        resumecheckwidth()
        // Phase 9: Check external declarations.
        for i, n := range externdcl {
                if n.Op == ONAME {
-                       typecheck(&externdcl[i], Erv)
+                       externdcl[i] = typecheck(externdcl[i], Erv)
                }
        }
 
 
        var_ := temp(t)
        if clear {
                a := Nod(OAS, var_, nil)
-               typecheck(&a, Etop)
+               a = typecheck(a, Etop)
                order.out = append(order.out, a)
        }
 
 func ordercopyexpr(n *Node, t *Type, order *Order, clear int) *Node {
        var_ := ordertemp(t, order, clear != 0)
        a := Nod(OAS, var_, n)
-       typecheck(&a, Etop)
+       a = typecheck(a, Etop)
        order.out = append(order.out, a)
        return var_
 }
                *a = *n
                a.Orig = a
                a.Left = l
-               typecheck(&a, Erv)
+               a = typecheck(a, Erv)
                return a
        }
 
                *a = *n
                a.Orig = a
                a.Left = l
-               typecheck(&a, Erv)
+               a = typecheck(a, Erv)
                return a
 
        case ODOTPTR, OIND:
                *a = *n
                a.Orig = a
                a.Left = l
-               typecheck(&a, Erv)
+               a = typecheck(a, Erv)
                return a
 
        case OINDEX, OINDEXMAP:
                a.Orig = a
                a.Left = l
                a.Right = r
-               typecheck(&a, Erv)
+               a = typecheck(a, Erv)
                return a
        }
 
 // Orderaddrtemp ensures that *np is okay to pass by address to runtime routines.
 // If the original argument *np is not okay, orderaddrtemp creates a tmp, emits
 // tmp = *np, and then sets *np to the tmp variable.
-func orderaddrtemp(np **Node, order *Order) {
-       n := *np
+func orderaddrtemp(n *Node, order *Order) *Node {
        if isaddrokay(n) {
-               return
+               return n
        }
-       *np = ordercopyexpr(n, n.Type, order, 0)
+       return ordercopyexpr(n, n.Type, order, 0)
 }
 
 type ordermarker int
                        n.Name.Keepalive = false
                        n.Addrtaken = true // ensure SSA keeps the n variable
                        kill = Nod(OVARLIVE, n, nil)
-                       typecheck(&kill, Etop)
+                       kill = typecheck(kill, Etop)
                        *out = append(*out, kill)
                }
                kill = Nod(OVARKILL, n, nil)
-               typecheck(&kill, Etop)
+               kill = typecheck(kill, Etop)
                *out = append(*out, kill)
        }
 }
 
 // Orderexprinplace orders the side effects in *np and
 // leaves them as the init list of the final *np.
-func orderexprinplace(np **Node, outer *Order) {
-       n := *np
+// The result of orderexprinplace MUST be assigned back to n, e.g.
+//     n.Left = orderexprinplace(n.Left, outer)
+func orderexprinplace(n *Node, outer *Order) *Node {
        var order Order
-       orderexpr(&n, &order, nil)
-       addinit(&n, order.out)
+       n = orderexpr(n, &order, nil)
+       n = addinit(n, order.out)
 
        // insert new temporaries from order
        // at head of outer list.
        outer.temp = append(outer.temp, order.temp...)
-
-       *np = n
+       return n
 }
 
 // Orderstmtinplace orders the side effects of the single statement *np
 // and replaces it with the resulting statement list.
-func orderstmtinplace(np **Node) {
-       n := *np
+// The result of orderstmtinplace MUST be assigned back to n, e.g.
+//     n.Left = orderstmtinplace(n.Left)
+func orderstmtinplace(n *Node) *Node {
        var order Order
        mark := marktemp(&order)
        orderstmt(n, &order)
        cleantemp(mark, &order)
-       *np = liststmt(order.out)
+       return liststmt(order.out)
 }
 
 // Orderinit moves n's init list to order->out.
        as := Nod(OAS2, nil, nil)
        as.List.Set(l1)
        as.Rlist.Set1(n)
-       typecheck(&as, Etop)
+       as = typecheck(as, Etop)
        orderstmt(as, order)
 
        return l2
 // Ordercall orders the call expression n.
 // n->op is OCALLMETH/OCALLFUNC/OCALLINTER or a builtin like OCOPY.
 func ordercall(n *Node, order *Order) {
-       orderexpr(&n.Left, order, nil)
-       orderexpr(&n.Right, order, nil) // ODDDARG temp
+       n.Left = orderexpr(n.Left, order, nil)
+       n.Right = orderexpr(n.Right, order, nil) // ODDDARG temp
        ordercallargs(&n.List, order)
 
        if n.Op == OCALLFUNC {
                        m := n.Left
                        n.Left = ordertemp(m.Type, order, false)
                        a := Nod(OAS, m, n.Left)
-                       typecheck(&a, Etop)
+                       a = typecheck(a, Etop)
                        order.out = append(order.out, a)
                }
 
                                }
                                n.List.SetIndex(i1, ordertemp(m.Type, order, false))
                                a = Nod(OAS, m, n.List.Index(i1))
-                               typecheck(&a, Etop)
+                               a = typecheck(a, Etop)
                                post = append(post, a)
                        } else if instrumenting && n.Op == OAS2FUNC && !isblank(n.List.Index(i1)) {
                                m = n.List.Index(i1)
                                t := ordertemp(m.Type, order, false)
                                n.List.SetIndex(i1, t)
                                a = Nod(OAS, m, t)
-                               typecheck(&a, Etop)
+                               a = typecheck(a, Etop)
                                post = append(post, a)
                        }
                }
 
        case OAS:
                t := marktemp(order)
-               orderexpr(&n.Left, order, nil)
-               orderexpr(&n.Right, order, n.Left)
+               n.Left = orderexpr(n.Left, order, nil)
+               n.Right = orderexpr(n.Right, order, n.Left)
                ordermapassign(n, order)
                cleantemp(t, order)
 
                ORECOVER,
                ORECV:
                t := marktemp(order)
-               orderexpr(&n.Left, order, nil)
-               orderexpr(&n.Right, order, nil)
+               n.Left = orderexpr(n.Left, order, nil)
+               n.Right = orderexpr(n.Right, order, nil)
                orderexprlist(n.List, order)
                orderexprlist(n.Rlist, order)
                switch n.Op {
                // a map index expression.
                t := marktemp(order)
 
-               orderexpr(&n.Left, order, nil)
+               n.Left = orderexpr(n.Left, order, nil)
                n.Left = ordersafeexpr(n.Left, order)
                tmp1 := treecopy(n.Left, 0)
                if tmp1.Op == OINDEXMAP {
                tmp1 = ordercopyexpr(tmp1, n.Left.Type, order, 0)
                // TODO(marvin): Fix Node.EType type union.
                n.Right = Nod(Op(n.Etype), tmp1, n.Right)
-               typecheck(&n.Right, Erv)
-               orderexpr(&n.Right, order, nil)
+               n.Right = typecheck(n.Right, Erv)
+               n.Right = orderexpr(n.Right, order, nil)
                n.Etype = 0
                n.Op = OAS
                ordermapassign(n, order)
 
                orderexprlist(n.List, order)
                r := n.Rlist.First()
-               orderexpr(&r.Left, order, nil)
-               orderexpr(&r.Right, order, nil)
+               r.Left = orderexpr(r.Left, order, nil)
+               r.Right = orderexpr(r.Right, order, nil)
 
                // See case OINDEXMAP below.
                if r.Right.Op == OARRAYBYTESTR {
                        r.Right.Op = OARRAYBYTESTRTMP
                }
-               orderaddrtemp(&r.Right, order)
+               r.Right = orderaddrtemp(r.Right, order)
                ordermapassign(n, order)
                cleantemp(t, order)
 
                t := marktemp(order)
 
                orderexprlist(n.List, order)
-               orderexpr(&n.Rlist.First().Left, order, nil) // i in i.(T)
+               n.Rlist.First().Left = orderexpr(n.Rlist.First().Left, order, nil) // i in i.(T)
                if isblank(n.List.First()) {
                        order.out = append(order.out, n)
                } else {
                        tmp1 := ordertemp(typ, order, haspointers(typ))
                        order.out = append(order.out, n)
                        r := Nod(OAS, n.List.First(), tmp1)
-                       typecheck(&r, Etop)
+                       r = typecheck(r, Etop)
                        ordermapassign(r, order)
                        n.List.Set([]*Node{tmp1, n.List.Second()})
                }
                t := marktemp(order)
 
                orderexprlist(n.List, order)
-               orderexpr(&n.Rlist.First().Left, order, nil) // arg to recv
+               n.Rlist.First().Left = orderexpr(n.Rlist.First().Left, order, nil) // arg to recv
                ch := n.Rlist.First().Left.Type
                tmp1 := ordertemp(ch.Type, order, haspointers(ch.Type))
                var tmp2 *Node
                }
                order.out = append(order.out, n)
                r := Nod(OAS, n.List.First(), tmp1)
-               typecheck(&r, Etop)
+               r = typecheck(r, Etop)
                ordermapassign(r, order)
                r = Nod(OAS, n.List.Second(), tmp2)
-               typecheck(&r, Etop)
+               r = typecheck(r, Etop)
                ordermapassign(r, order)
                n.List.Set([]*Node{tmp1, tmp2})
                cleantemp(t, order)
 
        case ODELETE:
                t := marktemp(order)
-               orderexpr(n.List.Addr(0), order, nil)
-               orderexpr(n.List.Addr(1), order, nil)
-               orderaddrtemp(n.List.Addr(1), order) // map key
+               n.List.SetIndex(0, orderexpr(n.List.Index(0), order, nil))
+               n.List.SetIndex(1, orderexpr(n.List.Index(1), order, nil))
+               n.List.SetIndex(1, orderaddrtemp(n.List.Index(1), order)) // map key
                order.out = append(order.out, n)
                cleantemp(t, order)
 
        case OFOR:
                t := marktemp(order)
 
-               orderexprinplace(&n.Left, order)
+               n.Left = orderexprinplace(n.Left, order)
                var l []*Node
                cleantempnopop(t, order, &l)
                n.Nbody.Set(append(l, n.Nbody.Slice()...))
                orderblockNodes(&n.Nbody)
-               orderstmtinplace(&n.Right)
+               n.Right = orderstmtinplace(n.Right)
                order.out = append(order.out, n)
                cleantemp(t, order)
 
        case OIF:
                t := marktemp(order)
 
-               orderexprinplace(&n.Left, order)
+               n.Left = orderexprinplace(n.Left, order)
                var l []*Node
                cleantempnopop(t, order, &l)
                n.Nbody.Set(append(l, n.Nbody.Slice()...))
        case OPANIC:
                t := marktemp(order)
 
-               orderexpr(&n.Left, order, nil)
+               n.Left = orderexpr(n.Left, order, nil)
                if !Isinter(n.Left.Type) {
-                       orderaddrtemp(&n.Left, order)
+                       n.Left = orderaddrtemp(n.Left, order)
                }
                order.out = append(order.out, n)
                cleantemp(t, order)
        case ORANGE:
                t := marktemp(order)
 
-               orderexpr(&n.Right, order, nil)
+               n.Right = orderexpr(n.Right, order, nil)
                switch n.Type.Etype {
                default:
                        Fatalf("orderstmt range %v", n.Type)
                        if r.Type.Etype == TSTRING && r.Type != Types[TSTRING] {
                                r = Nod(OCONV, r, nil)
                                r.Type = Types[TSTRING]
-                               typecheck(&r, Erv)
+                               r = typecheck(r, Erv)
                        }
 
                        n.Right = ordercopyexpr(r, r.Type, order, 0)
                        prealloc[n] = ordertemp(Types[TUINT8], order, true)
                }
                for i := range n.List.Slice() {
-                       orderexprinplace(n.List.Addr(i), order)
+                       n.List.SetIndex(i, orderexprinplace(n.List.Index(i), order))
                }
                orderblockNodes(&n.Nbody)
                order.out = append(order.out, n)
                                        // r->left is x, r->ntest is ok, r->right is ORECV, r->right->left is c.
                                        // r->left == N means 'case <-c'.
                                        // c is always evaluated; x and ok are only evaluated when assigned.
-                                       orderexpr(&r.Right.Left, order, nil)
+                                       r.Right.Left = orderexpr(r.Right.Left, order, nil)
 
                                        if r.Right.Left.Op != ONAME {
                                                r.Right.Left = ordercopyexpr(r.Right.Left, r.Right.Left.Type, order, 0)
 
                                                if r.Colas {
                                                        tmp2 = Nod(ODCL, tmp1, nil)
-                                                       typecheck(&tmp2, Etop)
+                                                       tmp2 = typecheck(tmp2, Etop)
                                                        n2.Ninit.Append(tmp2)
                                                }
 
                                                r.Left = ordertemp(r.Right.Left.Type.Type, order, haspointers(r.Right.Left.Type.Type))
                                                tmp2 = Nod(OAS, tmp1, r.Left)
-                                               typecheck(&tmp2, Etop)
+                                               tmp2 = typecheck(tmp2, Etop)
                                                n2.Ninit.Append(tmp2)
                                        }
 
                                                tmp1 = r.List.First()
                                                if r.Colas {
                                                        tmp2 = Nod(ODCL, tmp1, nil)
-                                                       typecheck(&tmp2, Etop)
+                                                       tmp2 = typecheck(tmp2, Etop)
                                                        n2.Ninit.Append(tmp2)
                                                }
 
                                                r.List.Set1(ordertemp(tmp1.Type, order, false))
                                                tmp2 = Nod(OAS, tmp1, r.List.First())
-                                               typecheck(&tmp2, Etop)
+                                               tmp2 = typecheck(tmp2, Etop)
                                                n2.Ninit.Append(tmp2)
                                        }
                                        n2.Ninit.Set(orderblock(n2.Ninit))
 
                                        // case c <- x
                                        // r->left is c, r->right is x, both are always evaluated.
-                                       orderexpr(&r.Left, order, nil)
+                                       r.Left = orderexpr(r.Left, order, nil)
 
                                        if !istemp(r.Left) {
                                                r.Left = ordercopyexpr(r.Left, r.Left.Type, order, 0)
                                        }
-                                       orderexpr(&r.Right, order, nil)
+                                       r.Right = orderexpr(r.Right, order, nil)
                                        if !istemp(r.Right) {
                                                r.Right = ordercopyexpr(r.Right, r.Right.Type, order, 0)
                                        }
        case OSEND:
                t := marktemp(order)
 
-               orderexpr(&n.Left, order, nil)
-               orderexpr(&n.Right, order, nil)
-               orderaddrtemp(&n.Right, order)
+               n.Left = orderexpr(n.Left, order, nil)
+               n.Right = orderexpr(n.Right, order, nil)
+               n.Right = orderaddrtemp(n.Right, order)
                order.out = append(order.out, n)
                cleantemp(t, order)
 
        case OSWITCH:
                t := marktemp(order)
 
-               orderexpr(&n.Left, order, nil)
+               n.Left = orderexpr(n.Left, order, nil)
                for _, n4 := range n.List.Slice() {
                        if n4.Op != OXCASE {
                                Fatalf("order switch case %v", Oconv(n4.Op, 0))
 func orderexprlist(l Nodes, order *Order) {
        s := l.Slice()
        for i := range s {
-               orderexpr(&s[i], order, nil)
+               s[i] = orderexpr(s[i], order, nil)
        }
 }
 
 func orderexprlistinplace(l Nodes, order *Order) {
        s := l.Slice()
        for i := range s {
-               orderexprinplace(&s[i], order)
+               s[i] = orderexprinplace(s[i], order)
        }
 }
 
 // If this is part of an assignment lhs = *np, lhs is given.
 // Otherwise lhs == nil. (When lhs != nil it may be possible
 // to avoid copying the result of the expression to a temporary.)
-func orderexpr(np **Node, order *Order, lhs *Node) {
-       n := *np
+// The result of orderexpr MUST be assigned back to n, e.g.
+//     n.Left = orderexpr(n.Left, order, lhs)
+func orderexpr(n *Node, order *Order, lhs *Node) *Node {
        if n == nil {
-               return
+               return n
        }
 
        lno := setlineno(n)
 
        switch n.Op {
        default:
-               orderexpr(&n.Left, order, nil)
-               orderexpr(&n.Right, order, nil)
+               n.Left = orderexpr(n.Left, order, nil)
+               n.Right = orderexpr(n.Right, order, nil)
                orderexprlist(n.List, order)
                orderexprlist(n.Rlist, order)
 
                }
 
        case OCMPSTR:
-               orderexpr(&n.Left, order, nil)
-               orderexpr(&n.Right, order, nil)
+               n.Left = orderexpr(n.Left, order, nil)
+               n.Right = orderexpr(n.Right, order, nil)
 
                // Mark string(byteSlice) arguments to reuse byteSlice backing
                // buffer during conversion. String comparison does not
 
                // key must be addressable
        case OINDEXMAP:
-               orderexpr(&n.Left, order, nil)
+               n.Left = orderexpr(n.Left, order, nil)
 
-               orderexpr(&n.Right, order, nil)
+               n.Right = orderexpr(n.Right, order, nil)
 
                // For x = m[string(k)] where k is []byte, the allocation of
                // backing bytes for the string can be avoided by reusing
                        n.Right.Op = OARRAYBYTESTRTMP
                }
 
-               orderaddrtemp(&n.Right, order)
+               n.Right = orderaddrtemp(n.Right, order)
                if n.Etype == 0 {
                        // use of value (not being assigned);
                        // make copy in temporary.
                // concrete type (not interface) argument must be addressable
        // temporary to pass to runtime.
        case OCONVIFACE:
-               orderexpr(&n.Left, order, nil)
+               n.Left = orderexpr(n.Left, order, nil)
 
                if !Isinter(n.Left.Type) {
-                       orderaddrtemp(&n.Left, order)
+                       n.Left = orderaddrtemp(n.Left, order)
                }
 
        case OANDAND, OOROR:
                mark := marktemp(order)
-               orderexpr(&n.Left, order, nil)
+               n.Left = orderexpr(n.Left, order, nil)
 
                // Clean temporaries from first branch at beginning of second.
                // Leave them on the stack so that they can be killed in the outer
 
                cleantempnopop(mark, order, &s)
                n.Right.Ninit.Set(append(s, n.Right.Ninit.Slice()...))
-               orderexprinplace(&n.Right, order)
+               n.Right = orderexprinplace(n.Right, order)
 
        case OCALLFUNC,
                OCALLINTER,
                }
 
        case OSLICE, OSLICEARR, OSLICESTR:
-               orderexpr(&n.Left, order, nil)
-               orderexpr(&n.Right.Left, order, nil)
+               n.Left = orderexpr(n.Left, order, nil)
+               n.Right.Left = orderexpr(n.Right.Left, order, nil)
                n.Right.Left = ordercheapexpr(n.Right.Left, order)
-               orderexpr(&n.Right.Right, order, nil)
+               n.Right.Right = orderexpr(n.Right.Right, order, nil)
                n.Right.Right = ordercheapexpr(n.Right.Right, order)
                if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) {
                        n = ordercopyexpr(n, n.Type, order, 0)
                }
 
        case OSLICE3, OSLICE3ARR:
-               orderexpr(&n.Left, order, nil)
-               orderexpr(&n.Right.Left, order, nil)
+               n.Left = orderexpr(n.Left, order, nil)
+               n.Right.Left = orderexpr(n.Right.Left, order, nil)
                n.Right.Left = ordercheapexpr(n.Right.Left, order)
-               orderexpr(&n.Right.Right.Left, order, nil)
+               n.Right.Right.Left = orderexpr(n.Right.Right.Left, order, nil)
                n.Right.Right.Left = ordercheapexpr(n.Right.Right.Left, order)
-               orderexpr(&n.Right.Right.Right, order, nil)
+               n.Right.Right.Right = orderexpr(n.Right.Right.Right, order, nil)
                n.Right.Right.Right = ordercheapexpr(n.Right.Right.Right, order)
                if lhs == nil || lhs.Op != ONAME && !samesafeexpr(lhs, n.Left) {
                        n = ordercopyexpr(n, n.Type, order, 0)
                }
 
        case OARRAYLIT, OCALLPART:
-               orderexpr(&n.Left, order, nil)
-               orderexpr(&n.Right, order, nil)
+               n.Left = orderexpr(n.Left, order, nil)
+               n.Right = orderexpr(n.Right, order, nil)
                orderexprlist(n.List, order)
                orderexprlist(n.Rlist, order)
                if n.Noescape {
                }
 
        case ODOTTYPE, ODOTTYPE2:
-               orderexpr(&n.Left, order, nil)
+               n.Left = orderexpr(n.Left, order, nil)
                // TODO(rsc): The Isfat is for consistency with componentgen and walkexpr.
                // It needs to be removed in all three places.
                // That would allow inlining x.(struct{*int}) the same as x.(*int).
                }
 
        case ORECV:
-               orderexpr(&n.Left, order, nil)
+               n.Left = orderexpr(n.Left, order, nil)
                n = ordercopyexpr(n, n.Type, order, 1)
 
        case OEQ, ONE:
-               orderexpr(&n.Left, order, nil)
-               orderexpr(&n.Right, order, nil)
+               n.Left = orderexpr(n.Left, order, nil)
+               n.Right = orderexpr(n.Right, order, nil)
                t := n.Left.Type
                if t.Etype == TSTRUCT || Isfixedarray(t) {
                        // for complex comparisons, we need both args to be
                        // addressable so we can pass them to the runtime.
-                       orderaddrtemp(&n.Left, order)
-                       orderaddrtemp(&n.Right, order)
+                       n.Left = orderaddrtemp(n.Left, order)
+                       n.Right = orderaddrtemp(n.Right, order)
                }
        }
 
        lineno = lno
-
-       *np = n
+       return n
 }
 
                for _, t := range Curfn.Type.Results().Fields().Slice() {
                        if t.Nname != nil {
                                n := Nod(OAS, t.Nname, nil)
-                               typecheck(&n, Etop)
+                               n = typecheck(n, Etop)
                                Curfn.Nbody.Set(append([]*Node{n}, Curfn.Nbody.Slice()...))
                        }
                }
 
                        n1 := Nod(OCONVNOP, n.Left, nil)
                        n1.Type = Ptrto(Types[TUINT8])
                        n1 = Nod(OIND, n1, nil)
-                       typecheck(&n1, Erv)
+                       n1 = typecheck(n1, Erv)
                        callinstr(&n1, init, 0, skip)
                }
 
        addr := Nod(OADDR, n, nil)
        l := temp(Ptrto(n.Type))
        as := Nod(OAS, l, addr)
-       typecheck(&as, Etop)
-       walkexpr(&as, init)
+       as = typecheck(as, Etop)
+       as = walkexpr(as, init)
        init.Append(as)
        ind := Nod(OIND, l, nil)
-       typecheck(&ind, Erv)
-       walkexpr(&ind, init)
+       ind = typecheck(ind, Erv)
+       ind = walkexpr(ind, init)
        return ind
 }
 
 
        // 3. typecheck body.
        // 4. decldepth--.
 
-       typecheck(&n.Right, Erv)
+       n.Right = typecheck(n.Right, Erv)
 
        t := n.Right.Type
        if t == nil {
        ls = n.List.Slice()
        for i1, n1 := range ls {
                if n1.Name == nil || n1.Name.Defn != n {
-                       typecheck(&ls[i1], Erv|Easgn)
+                       ls[i1] = typecheck(ls[i1], Erv|Easgn)
                }
        }
 
        ls = n.List.Slice()
        for i1, n1 := range ls {
                if n1.Typecheck == 0 {
-                       typecheck(&ls[i1], Erv|Easgn)
+                       ls[i1] = typecheck(ls[i1], Erv|Easgn)
                }
        }
 
                        tmp.Right.Type = Types[Tptr]
                        tmp.Right.Typecheck = 1
                        a = Nod(OAS, hp, tmp)
-                       typecheck(&a, Etop)
+                       a = typecheck(a, Etop)
                        n.Right.Ninit.Set1(a)
                }
 
 
                fn := syslook("mapiterinit")
 
-               substArgTypes(&fn, t.Key(), t.Type, th)
+               fn = substArgTypes(fn, t.Key(), t.Type, th)
                init = append(init, mkcall1(fn, nil, nil, typename(t), ha, Nod(OADDR, hit, nil)))
                n.Left = Nod(ONE, NodSym(ODOT, hit, keysym), nodnil())
 
                fn = syslook("mapiternext")
-               substArgTypes(&fn, th)
+               fn = substArgTypes(fn, th)
                n.Right = mkcall1(fn, nil, nil, Nod(OADDR, hit, nil))
 
                key := NodSym(ODOT, hit, keysym)
        typecheckslice(init, Etop)
        n.Ninit.Append(init...)
        typecheckslice(n.Left.Ninit.Slice(), Etop)
-       typecheck(&n.Left, Erv)
-       typecheck(&n.Right, Etop)
+       n.Left = typecheck(n.Left, Erv)
+       n.Right = typecheck(n.Right, Etop)
        typecheckslice(body, Etop)
        n.Nbody.Set(append(body, n.Nbody.Slice()...))
-       walkstmt(&n)
+       n = walkstmt(n)
 
        lineno = lno
 }
 
        n.Nbody.Append(v1)
 
-       typecheck(&n.Left, Erv)
+       n.Left = typecheck(n.Left, Erv)
        typecheckslice(n.Nbody.Slice(), Etop)
-       walkstmt(&n)
+       n = walkstmt(n)
        return true
 }
 
                } else if ncase.List.Len() > 1 {
                        Yyerror("select cases cannot be lists")
                } else {
-                       n = typecheck(ncase.List.Addr(0), Etop)
+                       ncase.List.SetIndex(0, typecheck(ncase.List.Index(0), Etop))
+                       n = ncase.List.Index(0)
                        ncase.Left = n
                        ncase.List.Set(nil)
                        setlineno(n)
                                }
 
                                if n.Left == nil {
-                                       typecheck(&nblank, Erv|Easgn)
+                                       nblank = typecheck(nblank, Erv|Easgn)
                                        n.Left = nblank
                                }
 
                                n.Right = nil
                                n.Left = nil
                                n.Typecheck = 0
-                               typecheck(&n, Etop)
+                               n = typecheck(n, Etop)
                        }
 
                        // if ch == nil { block() }; n;
                        ln.Set(l)
                        a.Nbody.Set1(mkcall("block", nil, &ln))
                        l = ln.Slice()
-                       typecheck(&a, Etop)
+                       a = typecheck(a, Etop)
                        l = append(l, a)
                        l = append(l, n)
                }
                switch n.Op {
                case OSEND:
                        n.Right = Nod(OADDR, n.Right, nil)
-                       typecheck(&n.Right, Erv)
+                       n.Right = typecheck(n.Right, Erv)
 
                case OSELRECV, OSELRECV2:
                        if n.Op == OSELRECV2 && n.List.Len() == 0 {
                        }
                        if n.Op == OSELRECV2 {
                                n.List.SetIndex(0, Nod(OADDR, n.List.First(), nil))
-                               typecheck(n.List.Addr(0), Erv)
+                               n.List.SetIndex(0, typecheck(n.List.Index(0), Erv))
                        }
 
                        if n.Left == nil {
                                n.Left = nodnil()
                        } else {
                                n.Left = Nod(OADDR, n.Left, nil)
-                               typecheck(&n.Left, Erv)
+                               n.Left = typecheck(n.Left, Erv)
                        }
                }
        }
                        r.Left = mkcall1(chanfn("selectnbrecv2", 2, ch.Type), Types[TBOOL], &r.Ninit, typename(ch.Type), n.Left, n.List.First(), ch)
                }
 
-               typecheck(&r.Left, Erv)
+               r.Left = typecheck(r.Left, Erv)
                r.Nbody.Set(cas.Nbody.Slice())
                r.Rlist.Set(append(dflt.Ninit.Slice(), dflt.Nbody.Slice()...))
                sel.Nbody.Set1(r)
 
        selv = temp(selecttype(int32(sel.Xoffset)))
        r = Nod(OAS, selv, nil)
-       typecheck(&r, Etop)
+       r = typecheck(r, Etop)
        init = append(init, r)
        var_ = conv(conv(Nod(OADDR, selv, nil), Types[TUNSAFEPTR]), Ptrto(Types[TUINT8]))
        r = mkcall("newselect", nil, nil, var_, Nodintconst(selv.Type.Width), Nodintconst(sel.Xoffset))
-       typecheck(&r, Etop)
+       r = typecheck(r, Etop)
        init = append(init, r)
        // register cases
        for _, cas := range sel.List.Slice() {
        scase.List.Append(Nod(ODCLFIELD, newname(Lookup("so")), typenod(Types[TUINT16])))
        scase.List.Append(Nod(ODCLFIELD, newname(Lookup("receivedp")), typenod(Ptrto(Types[TUINT8]))))
        scase.List.Append(Nod(ODCLFIELD, newname(Lookup("releasetime")), typenod(Types[TUINT64])))
-       typecheck(&scase, Etype)
+       scase = typecheck(scase, Etype)
        scase.Type.Noalg = true
        scase.Type.Local = true
 
        sel.List.Append(Nod(ODCLFIELD, newname(Lookup("lockorderarr")), arr))
        arr = Nod(OTARRAY, Nodintconst(int64(size)), typenod(Types[TUINT16]))
        sel.List.Append(Nod(ODCLFIELD, newname(Lookup("pollorderarr")), arr))
-       typecheck(&sel, Etype)
+       sel = typecheck(sel, Etype)
        sel.Type.Noalg = true
        sel.Type.Local = true
 
 
 
 func litas(l *Node, r *Node, init *Nodes) {
        a := Nod(OAS, l, r)
-       typecheck(&a, Etop)
-       walkexpr(&a, init)
+       a = typecheck(a, Etop)
+       a = walkexpr(a, init)
        init.Append(a)
 }
 
                a = NodSym(ODOT, var_, index.Sym)
 
                a = Nod(OAS, a, value)
-               typecheck(&a, Etop)
+               a = typecheck(a, Etop)
                if pass == 1 {
-                       walkexpr(&a, init) // add any assignments in r to top
+                       a = walkexpr(a, init) // add any assignments in r to top
                        if a.Op != OAS {
                                Fatalf("structlit: not as")
                        }
                        a.Dodata = 2
                } else {
-                       orderstmtinplace(&a)
-                       walkstmt(&a)
+                       a = orderstmtinplace(a)
+                       a = walkstmt(a)
                }
 
                init.Append(a)
                a = Nod(OINDEX, var_, index)
 
                a = Nod(OAS, a, value)
-               typecheck(&a, Etop)
+               a = typecheck(a, Etop)
                if pass == 1 {
-                       walkexpr(&a, init)
+                       a = walkexpr(a, init)
                        if a.Op != OAS {
                                Fatalf("arraylit: not as")
                        }
                        a.Dodata = 2
                } else {
-                       orderstmtinplace(&a)
-                       walkstmt(&a)
+                       a = orderstmtinplace(a)
+                       a = walkstmt(a)
                }
 
                init.Append(a)
                a := Nod(OSLICE, vstat, Nod(OKEY, nil, nil))
 
                a = Nod(OAS, var_, a)
-               typecheck(&a, Etop)
+               a = typecheck(a, Etop)
                a.Dodata = 2
                init.Append(a)
                return
 
                if vstat == nil {
                        a = Nod(OAS, x, nil)
-                       typecheck(&a, Etop)
+                       a = typecheck(a, Etop)
                        init.Append(a) // zero new temp
                }
 
                a = temp(t)
                if vstat == nil {
                        a = Nod(OAS, temp(t), nil)
-                       typecheck(&a, Etop)
+                       a = typecheck(a, Etop)
                        init.Append(a) // zero new temp
                        a = a.Left
                }
        }
 
        a = Nod(OAS, vauto, a)
-       typecheck(&a, Etop)
-       walkexpr(&a, init)
+       a = typecheck(a, Etop)
+       a = walkexpr(a, init)
        init.Append(a)
 
        if vstat != nil {
                a = Nod(OIND, vauto, nil)
 
                a = Nod(OAS, a, vstat)
-               typecheck(&a, Etop)
-               walkexpr(&a, init)
+               a = typecheck(a, Etop)
+               a = walkexpr(a, init)
                init.Append(a)
        }
 
        // make slice out of heap (5)
        a = Nod(OAS, var_, Nod(OSLICE, vauto, Nod(OKEY, nil, nil)))
 
-       typecheck(&a, Etop)
-       orderstmtinplace(&a)
-       walkstmt(&a)
+       a = typecheck(a, Etop)
+       a = orderstmtinplace(a)
+       a = walkstmt(a)
        init.Append(a)
        // put dynamics into slice (6)
        for _, r := range n.List.Slice() {
                setlineno(value)
                a = Nod(OAS, a, value)
 
-               typecheck(&a, Etop)
-               orderstmtinplace(&a)
-               walkstmt(&a)
+               a = typecheck(a, Etop)
+               a = orderstmtinplace(a)
+               a = walkstmt(a)
                init.Append(a)
        }
 }
                                a = Nod(OINDEX, vstat, a)
                                a = NodSym(ODOT, a, syma)
                                a = Nod(OAS, a, index)
-                               typecheck(&a, Etop)
-                               walkexpr(&a, init)
+                               a = typecheck(a, Etop)
+                               a = walkexpr(a, init)
                                a.Dodata = 2
                                init.Append(a)
 
                                a = Nod(OINDEX, vstat, a)
                                a = NodSym(ODOT, a, symb)
                                a = Nod(OAS, a, value)
-                               typecheck(&a, Etop)
-                               walkexpr(&a, init)
+                               a = typecheck(a, Etop)
+                               a = walkexpr(a, init)
                                a.Dodata = 2
                                init.Append(a)
 
                a.Left = Nod(OLT, index, Nodintconst(tarr.Bound))
                a.Right = Nod(OAS, index, Nod(OADD, index, Nodintconst(1)))
 
-               typecheck(&a, Etop)
-               walkstmt(&a)
+               a = typecheck(a, Etop)
+               a = walkstmt(a)
                init.Append(a)
        }
 
 
                setlineno(r.Left)
                a = Nod(OAS, key, r.Left)
-               typecheck(&a, Etop)
-               walkstmt(&a)
+               a = typecheck(a, Etop)
+               a = walkstmt(a)
                init.Append(a)
                setlineno(r.Right)
                a = Nod(OAS, val, r.Right)
-               typecheck(&a, Etop)
-               walkstmt(&a)
+               a = typecheck(a, Etop)
+               a = walkstmt(a)
                init.Append(a)
 
                setlineno(val)
                a = Nod(OAS, Nod(OINDEX, var_, key), val)
-               typecheck(&a, Etop)
-               walkstmt(&a)
+               a = typecheck(a, Etop)
+               a = walkstmt(a)
                init.Append(a)
 
                if nerr != nerrors {
 
        if key != nil {
                a = Nod(OVARKILL, key, nil)
-               typecheck(&a, Etop)
+               a = typecheck(a, Etop)
                init.Append(a)
                a = Nod(OVARKILL, val, nil)
-               typecheck(&a, Etop)
+               a = typecheck(a, Etop)
                init.Append(a)
        }
 }
                var r *Node
                if n.Right != nil {
                        r = Nod(OADDR, n.Right, nil)
-                       typecheck(&r, Erv)
+                       r = typecheck(r, Erv)
                } else {
                        r = Nod(ONEW, nil, nil)
                        r.Typecheck = 1
                        r.Esc = n.Esc
                }
 
-               walkexpr(&r, init)
+               r = walkexpr(r, init)
                a := Nod(OAS, var_, r)
 
-               typecheck(&a, Etop)
+               a = typecheck(a, Etop)
                init.Append(a)
 
                var_ = Nod(OIND, var_, nil)
-               typecheck(&var_, Erv|Easgn)
+               var_ = typecheck(var_, Erv|Easgn)
                anylit(ctxt, n.Left, var_, init)
 
        case OSTRUCTLIT:
                                // copy static to var
                                a := Nod(OAS, var_, vstat)
 
-                               typecheck(&a, Etop)
-                               walkexpr(&a, init)
+                               a = typecheck(a, Etop)
+                               a = walkexpr(a, init)
                                init.Append(a)
 
                                // add expressions to automatic
                // initialize of not completely specified
                if var_.isSimpleName() || n.List.Len() < t.NumFields() {
                        a := Nod(OAS, var_, nil)
-                       typecheck(&a, Etop)
-                       walkexpr(&a, init)
+                       a = typecheck(a, Etop)
+                       a = walkexpr(a, init)
                        init.Append(a)
                }
 
                                // copy static to automatic
                                a := Nod(OAS, var_, vstat)
 
-                               typecheck(&a, Etop)
-                               walkexpr(&a, init)
+                               a = typecheck(a, Etop)
+                               a = walkexpr(a, init)
                                init.Append(a)
 
                                // add expressions to automatic
                // initialize of not completely specified
                if var_.isSimpleName() || int64(n.List.Len()) < t.Bound {
                        a := Nod(OAS, var_, nil)
-                       typecheck(&a, Etop)
-                       walkexpr(&a, init)
+                       a = typecheck(a, Etop)
+                       a = walkexpr(a, init)
                        init.Append(a)
                }
 
 
 
 func aindex(b *Node, t *Type) *Type {
        bound := int64(-1) // open bound
-       typecheck(&b, Erv)
+       b = typecheck(b, Erv)
        if b != nil {
                switch consttype(b) {
                default:
 
        old := n
        old.Diag++ // silence errors about n; we'll issue one below
-       defaultlit(&n, t)
+       n = defaultlit(n, t)
        old.Diag--
        if t.Etype == TBLANK {
                return n
 // substArgTypes substitutes the given list of types for
 // successive occurrences of the "any" placeholder in the
 // type syntax expression n.Type.
-func substArgTypes(np **Node, types ...*Type) {
-       n := Nod(0, nil, nil)
-       *n = **np
-       *np = n
+// The result of substArgTypes MUST be assigned back to old, e.g.
+//     n.Left = substArgTypes(n.Left, t1, t2)
+func substArgTypes(old *Node, types ...*Type) *Node {
+       n := Nod(OXXX, nil, nil)
+       *n = *old // make shallow copy
 
        for _, t := range types {
                dowidth(t)
        if len(types) > 0 {
                Fatalf("substArgTypes: too many argument types")
        }
+       return n
 }
 
 // substAny walks t, replacing instances of "any" with successive
                r := Nod(OXXX, nil, nil)
                *r = *n
                r.Left = l
-               typecheck(&r, Erv)
-               walkexpr(&r, init)
+               r = typecheck(r, Erv)
+               r = walkexpr(r, init)
                return r
 
        case ODOTPTR, OIND:
                a := Nod(OXXX, nil, nil)
                *a = *n
                a.Left = l
-               walkexpr(&a, init)
+               a = walkexpr(a, init)
                return a
 
        case OINDEX, OINDEXMAP:
                *a = *n
                a.Left = l
                a.Right = r
-               walkexpr(&a, init)
+               a = walkexpr(a, init)
                return a
        }
 
 func copyexpr(n *Node, t *Type, init *Nodes) *Node {
        l := temp(t)
        a := Nod(OAS, l, n)
-       typecheck(&a, Etop)
-       walkexpr(&a, init)
+       a = typecheck(a, Etop)
+       a = walkexpr(a, init)
        init.Append(a)
        return l
 }
 // will give shortest unique addressing.
 // modify the tree with missing type names.
 func adddot(n *Node) *Node {
-       typecheck(&n.Left, Etype|Erv)
+       n.Left = typecheck(n.Left, Etype|Erv)
        n.Diag |= n.Left.Diag
        t := n.Left.Type
        if t == nil {
        if rcvr.Etype == TSTRUCT || rcvr.Etype == TINTER || Isptr[rcvr.Etype] && rcvr.Type.Etype == TSTRUCT {
                fn.Func.Dupok = true
        }
-       typecheck(&fn, Etop)
+       fn = typecheck(fn, Etop)
        typecheckslice(fn.Nbody.Slice(), Etop)
 
        inlcalls(fn)
        tfn.List.Append(Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
        tfn.List.Append(Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
        tfn.Rlist.Append(Nod(ODCLFIELD, nil, typenod(Types[TUINTPTR])))
-       typecheck(&tfn, Etype)
+       tfn = typecheck(tfn, Etype)
        n.Type = tfn.Type
        return n
 }
        return p
 }
 
-func addinit(np **Node, init []*Node) {
+// The result of addinit MUST be assigned back to n, e.g.
+//     n.Left = addinit(n.Left, init)
+func addinit(n *Node, init []*Node) *Node {
        if len(init) == 0 {
-               return
+               return n
        }
 
-       n := *np
        switch n.Op {
        // There may be multiple refs to this node;
        // introduce OCONVNOP to hold init list.
        case ONAME, OLITERAL:
                n = Nod(OCONVNOP, n, nil)
-
                n.Type = n.Left.Type
                n.Typecheck = 1
-               *np = n
        }
 
        n.Ninit.Set(append(init, n.Ninit.Slice()...))
        n.Ullman = UINF
+       return n
 }
 
 var reservedimports = []string{
 func checknil(x *Node, init *Nodes) {
        if Isinter(x.Type) {
                x = Nod(OITAB, x, nil)
-               typecheck(&x, Erv)
+               x = typecheck(x, Erv)
        }
 
        n := Nod(OCHECKNIL, x, nil)
 
        if n.Left != nil && n.Left.Op == OTYPESW {
                // type switch
                top = Etype
-               typecheck(&n.Left.Right, Erv)
+               n.Left.Right = typecheck(n.Left.Right, Erv)
                t = n.Left.Right.Type
                if t != nil && t.Etype != TINTER {
                        Yyerror("cannot type switch on non-interface value %v", Nconv(n.Left.Right, FmtLong))
                // expression switch
                top = Erv
                if n.Left != nil {
-                       typecheck(&n.Left, Erv)
-                       defaultlit(&n.Left, nil)
+                       n.Left = typecheck(n.Left, Erv)
+                       n.Left = defaultlit(n.Left, nil)
                        t = n.Left.Type
                } else {
                        t = Types[TBOOL]
                        ls := ncase.List.Slice()
                        for i1, n1 := range ls {
                                setlineno(n1)
-                               typecheck(&ls[i1], Erv|Etype)
+                               ls[i1] = typecheck(ls[i1], Erv|Etype)
                                n1 = ls[i1]
                                if n1.Type == nil || t == nil {
                                        continue
                                switch top {
                                // expression switch
                                case Erv:
-                                       defaultlit(&ls[i1], t)
+                                       ls[i1] = defaultlit(ls[i1], t)
                                        n1 = ls[i1]
                                        switch {
                                        case n1.Op == OTYPE:
                                        nvar.Name.Param.Ntype = typenod(n.Type)
                                }
 
-                               typecheck(&nvar, Erv|Easgn)
+                               nvar = typecheck(nvar, Erv|Easgn)
                                ncase.Rlist.SetIndex(0, nvar)
                        }
                }
        // convert switch {...} to switch true {...}
        if sw.Left == nil {
                sw.Left = Nodbool(true)
-               typecheck(&sw.Left, Erv)
+               sw.Left = typecheck(sw.Left, Erv)
        }
 
        if sw.Left.Op == OTYPESW {
                }
        }
 
-       walkexpr(&cond, &sw.Ninit)
+       cond = walkexpr(cond, &sw.Ninit)
        t := sw.Type
        if t == nil {
                return
                        a := Nod(OIF, nil, nil)
                        if (s.kind != switchKindTrue && s.kind != switchKindFalse) || assignop(n.Left.Type, s.exprname.Type, nil) == OCONVIFACE || assignop(s.exprname.Type, n.Left.Type, nil) == OCONVIFACE {
                                a.Left = Nod(OEQ, s.exprname, n.Left) // if name == val
-                               typecheck(&a.Left, Erv)
+                               a.Left = typecheck(a.Left, Erv)
                        } else if s.kind == switchKindTrue {
                                a.Left = n.Left // if val
                        } else {
                                // s.kind == switchKindFalse
                                a.Left = Nod(ONOT, n.Left, nil) // if !val
-                               typecheck(&a.Left, Erv)
+                               a.Left = typecheck(a.Left, Erv)
                        }
                        a.Nbody.Set1(n.Right) // goto l
 
        } else {
                a.Left = le
        }
-       typecheck(&a.Left, Erv)
+       a.Left = typecheck(a.Left, Erv)
        a.Nbody.Set1(s.walkCases(cc[:half]))
        a.Rlist.Set1(s.walkCases(cc[half:]))
        return a
                return
        }
 
-       walkexpr(&cond.Right, &sw.Ninit)
+       cond.Right = walkexpr(cond.Right, &sw.Ninit)
        if !Istype(cond.Right.Type, TINTER) {
                Yyerror("type switch must be on an interface")
                return
        s.facename = temp(cond.Right.Type)
 
        a := Nod(OAS, s.facename, cond.Right)
-       typecheck(&a, Etop)
+       a = typecheck(a, Etop)
        cas = append(cas, a)
 
        s.okname = temp(Types[TBOOL])
-       typecheck(&s.okname, Erv)
+       s.okname = typecheck(s.okname, Erv)
 
        s.hashname = temp(Types[TUINT32])
-       typecheck(&s.hashname, Erv)
+       s.hashname = typecheck(s.hashname, Erv)
 
        // set up labels and jumps
        casebody(sw, s.facename)
                blk.List.Set([]*Node{Nod(OLABEL, lbl, nil), def})
                def = blk
        }
-       typecheck(&i.Left, Erv)
+       i.Left = typecheck(i.Left, Erv)
        cas = append(cas, i)
 
        if !isnilinter(cond.Right.Type) {
        h.Xoffset = int64(2 * Widthptr) // offset of hash in runtime._type
        h.Bounded = true                // guaranteed not to fault
        a = Nod(OAS, s.hashname, h)
-       typecheck(&a, Etop)
+       a = typecheck(a, Etop)
        cas = append(cas, a)
 
        // insert type equality check into each case block
        var init []*Node
        if t.Rlist.Len() == 0 {
                name = nblank
-               typecheck(&nblank, Erv|Easgn)
+               nblank = typecheck(nblank, Erv|Easgn)
        } else {
                name = t.Rlist.First()
                init = []*Node{Nod(ODCL, name, nil)}
                a := Nod(OAS, name, nil)
-               typecheck(&a, Etop)
+               a = typecheck(a, Etop)
                init = append(init, a)
        }
 
        b := Nod(ODOTTYPE, s.facename, nil)
        b.Type = t.Left.Type // interface.(type)
        a.Rlist.Set1(b)
-       typecheck(&a, Etop)
+       a = typecheck(a, Etop)
        init = append(init, a)
 
        c := Nod(OIF, nil, nil)
                        }
                        a := Nod(OIF, nil, nil)
                        a.Left = Nod(OEQ, s.hashname, Nodintconst(int64(c.hash)))
-                       typecheck(&a.Left, Erv)
+                       a.Left = typecheck(a.Left, Erv)
                        a.Nbody.Set1(n.Right)
                        cas = append(cas, a)
                }
        half := len(cc) / 2
        a := Nod(OIF, nil, nil)
        a.Left = Nod(OLE, s.hashname, Nodintconst(int64(cc[half-1].hash)))
-       typecheck(&a.Left, Erv)
+       a.Left = typecheck(a.Left, Erv)
        a.Nbody.Set1(s.walkCases(cc[:half]))
        a.Rlist.Set1(s.walkCases(cc[half:]))
        return a
 
 
 func typecheckslice(l []*Node, top int) {
        for i := range l {
-               typecheck(&l[i], top)
+               l[i] = typecheck(l[i], top)
        }
 }
 
 
 var typecheck_tcstack []*Node
 
-// typecheck type checks node *np.
-// It replaces *np with a new pointer in some cases.
-// It returns the final value of *np as a convenience.
-func typecheck(np **Node, top int) *Node {
+// typecheck type checks node n.
+// The result of typecheck MUST be assigned back to n, e.g.
+//     n.Left = typecheck(n.Left, top)
+func typecheck(n *Node, top int) *Node {
        // cannot type check until all the source has been parsed
        if !typecheckok {
                Fatalf("early typecheck")
        }
 
-       n := *np
        if n == nil {
                return nil
        }
        // Resolve definition of name and value of iota lazily.
        n = resolve(n)
 
-       *np = n
-
        // Skip typecheck if already done.
        // But re-typecheck ONAME/OTYPE/OLITERAL/OPACK node in case context has changed.
        if n.Typecheck == 1 {
        n.Typecheck = 2
 
        typecheck_tcstack = append(typecheck_tcstack, n)
-       typecheck1(&n, top)
-       *np = n
+       n = typecheck1(n, top)
 
        n.Typecheck = 1
 
 // array/slice indexes. It is equivalent to defaultlit
 // except for constants of numerical kind, which are acceptable
 // whenever they can be represented by a value of type int.
-func indexlit(np **Node) {
-       n := *np
+// The result of indexlit MUST be assigned back to n, e.g.
+//     n.Left = indexlit(n.Left)
+func indexlit(n *Node) *Node {
        if n == nil || !isideal(n.Type) {
-               return
+               return n
        }
        switch consttype(n) {
        case CTINT, CTRUNE, CTFLT, CTCPLX:
-               defaultlit(np, Types[TINT])
+               n = defaultlit(n, Types[TINT])
        }
 
-       defaultlit(np, nil)
+       n = defaultlit(n, nil)
+       return n
 }
 
-func typecheck1(np **Node, top int) {
-       n := *np
-       defer func() {
-               *np = n
-       }()
-
+// The result of typecheck1 MUST be assigned back to n, e.g.
+//     n.Left = typecheck1(n.Left, top)
+func typecheck1(n *Node, top int) *Node {
        switch n.Op {
        case OXDOT, ODOT, ODOTPTR, ODOTMETH, ODOTINTER:
                // n.Sym is a field/method name, not a variable.
                        if n.Op == ONAME && n.Etype != 0 && top&Ecall == 0 {
                                Yyerror("use of builtin %v not in function call", n.Sym)
                                n.Type = nil
-                               return
+                               return n
                        }
 
                        typecheckdef(n)
                        if n.Op == ONONAME {
                                n.Type = nil
-                               return
+                               return n
                        }
                }
        }
                        if isblank(n) {
                                Yyerror("cannot use _ as value")
                                n.Type = nil
-                               return
+                               return n
                        }
 
                        n.Used = true
                if top&Ecall == 0 && isunsafebuiltin(n) {
                        Yyerror("%v is not an expression, must be called", n)
                        n.Type = nil
-                       return
+                       return n
                }
 
                ok |= Erv
        case OPACK:
                Yyerror("use of package %v without selector", n.Sym)
                n.Type = nil
-               return
+               return n
 
        case ODDD:
                break
 
                if n.Type == nil {
                        n.Type = nil
-                       return
+                       return n
                }
 
        case OTARRAY:
                                Yyerror("use of [...] array outside of array literal")
                        }
                } else {
-                       l := typecheck(&n.Left, Erv)
+                       n.Left = typecheck(n.Left, Erv)
+                       l := n.Left
                        var v Val
                        switch consttype(l) {
                        case CTINT, CTRUNE:
                                        Yyerror("invalid array bound %v", l)
                                }
                                n.Type = nil
-                               return
+                               return n
                        }
 
                        t.Bound = v.U.(*Mpint).Int64()
                        if doesoverflow(v, Types[TINT]) {
                                Yyerror("array bound is too large")
                                n.Type = nil
-                               return
+                               return n
                        } else if t.Bound < 0 {
                                Yyerror("array bound must be non-negative")
                                n.Type = nil
-                               return
+                               return n
                        }
                }
 
-               typecheck(&r, Etype)
+               r = typecheck(r, Etype)
                if r.Type == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                t.Type = r.Type
                n.Op = OTYPE
 
        case OTMAP:
                ok |= Etype
-               l := typecheck(&n.Left, Etype)
-               r := typecheck(&n.Right, Etype)
+               n.Left = typecheck(n.Left, Etype)
+               n.Right = typecheck(n.Right, Etype)
+               l := n.Left
+               r := n.Right
                if l.Type == nil || r.Type == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                n.Op = OTYPE
                n.Type = maptype(l.Type, r.Type)
 
        case OTCHAN:
                ok |= Etype
-               l := typecheck(&n.Left, Etype)
+               n.Left = typecheck(n.Left, Etype)
+               l := n.Left
                if l.Type == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                t := typ(TCHAN)
                t.Type = l.Type
                n.Type = tostruct(n.List.Slice())
                if n.Type == nil || n.Type.Broke {
                        n.Type = nil
-                       return
+                       return n
                }
                n.List.Set(nil)
 
                n.Type = tointerface(n.List.Slice())
                if n.Type == nil {
                        n.Type = nil
-                       return
+                       return n
                }
 
        case OTFUNC:
                n.Type = functype(n.Left, n.List.Slice(), n.Rlist.Slice())
                if n.Type == nil {
                        n.Type = nil
-                       return
+                       return n
                }
 
        // type or expr
                        ntop |= Eindir
                }
                ntop |= top & Ecomplit
-               l := typecheck(&n.Left, ntop)
+               n.Left = typecheck(n.Left, ntop)
+               l := n.Left
                t := l.Type
                if t == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                if l.Op == OTYPE {
                        ok |= Etype
                        if top&(Erv|Etop) != 0 {
                                Yyerror("invalid indirect of %v", Nconv(n.Left, FmtLong))
                                n.Type = nil
-                               return
+                               return n
                        }
 
                        break OpSwitch
                var r *Node
                if n.Op == OASOP {
                        ok |= Etop
-                       l = typecheck(&n.Left, Erv)
-                       r = typecheck(&n.Right, Erv)
+                       n.Left = typecheck(n.Left, Erv)
+                       n.Right = typecheck(n.Right, Erv)
+                       l = n.Left
+                       r = n.Right
                        checkassign(n, n.Left)
                        if l.Type == nil || r.Type == nil {
                                n.Type = nil
-                               return
+                               return n
                        }
                        if n.Implicit && !okforarith[l.Type.Etype] {
                                Yyerror("invalid operation: %v (non-numeric type %v)", n, l.Type)
                                n.Type = nil
-                               return
+                               return n
                        }
                        // TODO(marvin): Fix Node.EType type union.
                        op = Op(n.Etype)
                } else {
                        ok |= Erv
-                       l = typecheck(&n.Left, Erv|top&Eiota)
-                       r = typecheck(&n.Right, Erv|top&Eiota)
+                       n.Left = typecheck(n.Left, Erv|top&Eiota)
+                       n.Right = typecheck(n.Right, Erv|top&Eiota)
+                       l = n.Left
+                       r = n.Right
                        if l.Type == nil || r.Type == nil {
                                n.Type = nil
-                               return
+                               return n
                        }
                        op = n.Op
                }
                if op == OLSH || op == ORSH {
-                       defaultlit(&r, Types[TUINT])
+                       r = defaultlit(r, Types[TUINT])
                        n.Right = r
                        t := r.Type
                        if !Isint[t.Etype] || Issigned[t.Etype] {
                                Yyerror("invalid operation: %v (shift count type %v, must be unsigned integer)", n, r.Type)
                                n.Type = nil
-                               return
+                               return n
                        }
 
                        t = l.Type
                        if t != nil && t.Etype != TIDEAL && !Isint[t.Etype] {
                                Yyerror("invalid operation: %v (shift of type %v)", n, t)
                                n.Type = nil
-                               return
+                               return n
                        }
 
                        // no defaultlit for left
                }
 
                // ideal mixed with non-ideal
-               defaultlit2(&l, &r, false)
+               l, r = defaultlit2(l, r, false)
 
                n.Left = l
                n.Right = r
                if l.Type == nil || r.Type == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                t := l.Type
                if t.Etype == TIDEAL {
                                        if Isinter(r.Type) && !Isinter(l.Type) && algtype1(l.Type, nil) == ANOEQ {
                                                Yyerror("invalid operation: %v (operator %v not defined on %s)", n, Oconv(op, 0), typekind(l.Type))
                                                n.Type = nil
-                                               return
+                                               return n
                                        }
 
                                        dowidth(l.Type)
                                        if Isinter(l.Type) && !Isinter(r.Type) && algtype1(r.Type, nil) == ANOEQ {
                                                Yyerror("invalid operation: %v (operator %v not defined on %s)", n, Oconv(op, 0), typekind(r.Type))
                                                n.Type = nil
-                                               return
+                                               return n
                                        }
 
                                        dowidth(r.Type)
                }
 
                if t.Etype != TIDEAL && !Eqtype(l.Type, r.Type) {
-                       defaultlit2(&l, &r, true)
+                       l, r = defaultlit2(l, r, true)
                        if Isinter(r.Type) == Isinter(l.Type) || aop == 0 {
                                Yyerror("invalid operation: %v (mismatched types %v and %v)", n, l.Type, r.Type)
                                n.Type = nil
-                               return
+                               return n
                        }
                }
 
                if !okfor[op][et] {
                        Yyerror("invalid operation: %v (operator %v not defined on %s)", n, Oconv(op, 0), typekind(t))
                        n.Type = nil
-                       return
+                       return n
                }
 
                // okfor allows any array == array, map == map, func == func.
                if Isfixedarray(l.Type) && algtype1(l.Type, nil) == ANOEQ {
                        Yyerror("invalid operation: %v (%v cannot be compared)", n, l.Type)
                        n.Type = nil
-                       return
+                       return n
                }
 
                if Isslice(l.Type) && !isnil(l) && !isnil(r) {
                        Yyerror("invalid operation: %v (slice can only be compared to nil)", n)
                        n.Type = nil
-                       return
+                       return n
                }
 
                if l.Type.Etype == TMAP && !isnil(l) && !isnil(r) {
                        Yyerror("invalid operation: %v (map can only be compared to nil)", n)
                        n.Type = nil
-                       return
+                       return n
                }
 
                if l.Type.Etype == TFUNC && !isnil(l) && !isnil(r) {
                        Yyerror("invalid operation: %v (func can only be compared to nil)", n)
                        n.Type = nil
-                       return
+                       return n
                }
 
                var badtype *Type
                if l.Type.Etype == TSTRUCT && algtype1(l.Type, &badtype) == ANOEQ {
                        Yyerror("invalid operation: %v (struct containing %v cannot be compared)", n, badtype)
                        n.Type = nil
-                       return
+                       return n
                }
 
                t = l.Type
                        evconst(n)
                        t = idealbool
                        if n.Op != OLITERAL {
-                               defaultlit2(&l, &r, true)
+                               l, r = defaultlit2(l, r, true)
                                n.Left = l
                                n.Right = r
                        }
                        if r.Val().U.(*Mpint).CmpInt64(0) == 0 {
                                Yyerror("division by zero")
                                n.Type = nil
-                               return
+                               return n
                        }
                }
 
 
        case OCOM, OMINUS, ONOT, OPLUS:
                ok |= Erv
-               l := typecheck(&n.Left, Erv|top&Eiota)
+               n.Left = typecheck(n.Left, Erv|top&Eiota)
+               l := n.Left
                t := l.Type
                if t == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                if !okfor[n.Op][t.Etype] {
                        Yyerror("invalid operation: %v %v", Oconv(n.Op, 0), t)
                        n.Type = nil
-                       return
+                       return n
                }
 
                n.Type = t
        case OADDR:
                ok |= Erv
 
-               typecheck(&n.Left, Erv|Eaddr)
+               n.Left = typecheck(n.Left, Erv|Eaddr)
                if n.Left.Type == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                checklvalue(n.Left, "take the address of")
                r := outervalue(n.Left)
                if l.Name != nil && l.Name.Param != nil && l.Name.Param.Closure != nil {
                        l.Name.Param.Closure.Addrtaken = true
                }
-               defaultlit(&n.Left, nil)
+               n.Left = defaultlit(n.Left, nil)
                l = n.Left
                t := l.Type
                if t == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                n.Type = Ptrto(t)
                break OpSwitch
 
        case OCOMPLIT:
                ok |= Erv
-               typecheckcomplit(&n)
+               n = typecheckcomplit(n)
                if n.Type == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                break OpSwitch
 
                        n.Op = ODOT
                        if n.Left == nil {
                                n.Type = nil
-                               return
+                               return n
                        }
                }
 
-               typecheck(&n.Left, Erv|Etype)
+               n.Left = typecheck(n.Left, Erv|Etype)
 
-               defaultlit(&n.Left, nil)
+               n.Left = defaultlit(n.Left, nil)
 
                t := n.Left.Type
                if t == nil {
                        adderrorname(n)
                        n.Type = nil
-                       return
+                       return n
                }
 
                s := n.Sym
                                        Yyerror("%v undefined (type %v has no method %v)", n, t, n.Sym)
                                }
                                n.Type = nil
-                               return
+                               return n
                        }
 
                        if n.Type.Etype != TFUNC || n.Type.Recv() == nil {
                                Yyerror("type %v has no method %v", n.Left.Type, Sconv(n.Right.Sym, FmtShort))
                                n.Type = nil
                                n.Type = nil
-                               return
+                               return n
                        }
 
                        n.Op = ONAME
                        t = t.Type
                        if t == nil {
                                n.Type = nil
-                               return
+                               return n
                        }
                        n.Op = ODOTPTR
                        checkwidth(t)
                if isblanksym(n.Sym) {
                        Yyerror("cannot refer to blank field or method")
                        n.Type = nil
-                       return
+                       return n
                }
 
                if lookdot(n, t, 0) == nil {
                                }
                        }
                        n.Type = nil
-                       return
+                       return n
                }
 
                switch n.Op {
 
        case ODOTTYPE:
                ok |= Erv
-               typecheck(&n.Left, Erv)
-               defaultlit(&n.Left, nil)
+               n.Left = typecheck(n.Left, Erv)
+               n.Left = defaultlit(n.Left, nil)
                l := n.Left
                t := l.Type
                if t == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                if !Isinter(t) {
                        Yyerror("invalid type assertion: %v (non-interface type %v on left)", n, t)
                        n.Type = nil
-                       return
+                       return n
                }
 
                if n.Right != nil {
-                       typecheck(&n.Right, Etype)
+                       n.Right = typecheck(n.Right, Etype)
                        n.Type = n.Right.Type
                        n.Right = nil
                        if n.Type == nil {
-                               return
+                               return n
                        }
                }
 
                                        Yyerror("impossible type assertion:\n\t%v does not implement %v (missing %v method)", n.Type, t, missing.Sym)
                                }
                                n.Type = nil
-                               return
+                               return n
                        }
                }
 
 
        case OINDEX:
                ok |= Erv
-               typecheck(&n.Left, Erv)
-               defaultlit(&n.Left, nil)
-               implicitstar(&n.Left)
+               n.Left = typecheck(n.Left, Erv)
+               n.Left = defaultlit(n.Left, nil)
+               n.Left = implicitstar(n.Left)
                l := n.Left
-               typecheck(&n.Right, Erv)
+               n.Right = typecheck(n.Right, Erv)
                r := n.Right
                t := l.Type
                if t == nil || r.Type == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                switch t.Etype {
                default:
                        Yyerror("invalid operation: %v (type %v does not support indexing)", n, t)
                        n.Type = nil
-                       return
+                       return n
 
                case TSTRING, TARRAY:
-                       indexlit(&n.Right)
+                       n.Right = indexlit(n.Right)
                        if t.Etype == TSTRING {
                                n.Type = bytetype
                        } else {
 
                case TMAP:
                        n.Etype = 0
-                       defaultlit(&n.Right, t.Key())
+                       n.Right = defaultlit(n.Right, t.Key())
                        if n.Right.Type != nil {
                                n.Right = assignconv(n.Right, t.Key(), "map index")
                        }
 
        case ORECV:
                ok |= Etop | Erv
-               typecheck(&n.Left, Erv)
-               defaultlit(&n.Left, nil)
+               n.Left = typecheck(n.Left, Erv)
+               n.Left = defaultlit(n.Left, nil)
                l := n.Left
                t := l.Type
                if t == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                if t.Etype != TCHAN {
                        Yyerror("invalid operation: %v (receive from non-chan type %v)", n, t)
                        n.Type = nil
-                       return
+                       return n
                }
 
                if t.Chan&Crecv == 0 {
                        Yyerror("invalid operation: %v (receive from send-only type %v)", n, t)
                        n.Type = nil
-                       return
+                       return n
                }
 
                n.Type = t.Type
 
        case OSEND:
                ok |= Etop
-               l := typecheck(&n.Left, Erv)
-               typecheck(&n.Right, Erv)
-               defaultlit(&n.Left, nil)
+               n.Left = typecheck(n.Left, Erv)
+               l := n.Left
+               n.Right = typecheck(n.Right, Erv)
+               n.Left = defaultlit(n.Left, nil)
                l = n.Left
                t := l.Type
                if t == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                if t.Etype != TCHAN {
                        Yyerror("invalid operation: %v (send to non-chan type %v)", n, t)
                        n.Type = nil
-                       return
+                       return n
                }
 
                if t.Chan&Csend == 0 {
                        Yyerror("invalid operation: %v (send to receive-only type %v)", n, t)
                        n.Type = nil
-                       return
+                       return n
                }
 
-               defaultlit(&n.Right, t.Type)
+               n.Right = defaultlit(n.Right, t.Type)
                r := n.Right
                if r.Type == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                n.Right = assignconv(r, l.Type.Type, "send")
 
 
        case OSLICE:
                ok |= Erv
-               typecheck(&n.Left, top)
-               typecheck(&n.Right.Left, Erv)
-               typecheck(&n.Right.Right, Erv)
-               defaultlit(&n.Left, nil)
-               indexlit(&n.Right.Left)
-               indexlit(&n.Right.Right)
+               n.Left = typecheck(n.Left, top)
+               n.Right.Left = typecheck(n.Right.Left, Erv)
+               n.Right.Right = typecheck(n.Right.Right, Erv)
+               n.Left = defaultlit(n.Left, nil)
+               n.Right.Left = indexlit(n.Right.Left)
+               n.Right.Right = indexlit(n.Right.Right)
                l := n.Left
                if Isfixedarray(l.Type) {
                        if !islvalue(n.Left) {
                                Yyerror("invalid operation %v (slice of unaddressable value)", n)
                                n.Type = nil
-                               return
+                               return n
                        }
 
                        n.Left = Nod(OADDR, n.Left, nil)
                        n.Left.Implicit = true
-                       typecheck(&n.Left, Erv)
+                       n.Left = typecheck(n.Left, Erv)
                        l = n.Left
                }
 
                t := l.Type
                if t == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                var tp *Type
                if Istype(t, TSTRING) {
                } else {
                        Yyerror("cannot slice %v (type %v)", l, t)
                        n.Type = nil
-                       return
+                       return n
                }
 
                lo := n.Right.Left
                if lo != nil && !checksliceindex(l, lo, tp) {
                        n.Type = nil
-                       return
+                       return n
                }
                hi := n.Right.Right
                if hi != nil && !checksliceindex(l, hi, tp) {
                        n.Type = nil
-                       return
+                       return n
                }
                if !checksliceconst(lo, hi) {
                        n.Type = nil
-                       return
+                       return n
                }
                break OpSwitch
 
        case OSLICE3:
                ok |= Erv
-               typecheck(&n.Left, top)
-               typecheck(&n.Right.Left, Erv)
-               typecheck(&n.Right.Right.Left, Erv)
-               typecheck(&n.Right.Right.Right, Erv)
-               defaultlit(&n.Left, nil)
-               indexlit(&n.Right.Left)
-               indexlit(&n.Right.Right.Left)
-               indexlit(&n.Right.Right.Right)
+               n.Left = typecheck(n.Left, top)
+               n.Right.Left = typecheck(n.Right.Left, Erv)
+               n.Right.Right.Left = typecheck(n.Right.Right.Left, Erv)
+               n.Right.Right.Right = typecheck(n.Right.Right.Right, Erv)
+               n.Left = defaultlit(n.Left, nil)
+               n.Right.Left = indexlit(n.Right.Left)
+               n.Right.Right.Left = indexlit(n.Right.Right.Left)
+               n.Right.Right.Right = indexlit(n.Right.Right.Right)
                l := n.Left
                if Isfixedarray(l.Type) {
                        if !islvalue(n.Left) {
                                Yyerror("invalid operation %v (slice of unaddressable value)", n)
                                n.Type = nil
-                               return
+                               return n
                        }
 
                        n.Left = Nod(OADDR, n.Left, nil)
                        n.Left.Implicit = true
-                       typecheck(&n.Left, Erv)
+                       n.Left = typecheck(n.Left, Erv)
                        l = n.Left
                }
 
                t := l.Type
                if t == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                if Istype(t, TSTRING) {
                        Yyerror("invalid operation %v (3-index slice of string)", n)
                        n.Type = nil
-                       return
+                       return n
                }
 
                var tp *Type
                } else {
                        Yyerror("cannot slice %v (type %v)", l, t)
                        n.Type = nil
-                       return
+                       return n
                }
 
                lo := n.Right.Left
                if lo != nil && !checksliceindex(l, lo, tp) {
                        n.Type = nil
-                       return
+                       return n
                }
                mid := n.Right.Right.Left
                if mid != nil && !checksliceindex(l, mid, tp) {
                        n.Type = nil
-                       return
+                       return n
                }
                hi := n.Right.Right.Right
                if hi != nil && !checksliceindex(l, hi, tp) {
                        n.Type = nil
-                       return
+                       return n
                }
                if !checksliceconst(lo, hi) || !checksliceconst(lo, mid) || !checksliceconst(mid, hi) {
                        n.Type = nil
-                       return
+                       return n
                }
                break OpSwitch
 
                                        Yyerror("invalid use of ... with builtin %v", l)
                                }
                                n = r
-                               typecheck1(&n, top)
-                               return
+                               n = typecheck1(n, top)
+                               return n
                        }
                }
 
-               typecheck(&n.Left, Erv|Etype|Ecall|top&Eproc)
+               n.Left = typecheck(n.Left, Erv|Etype|Ecall|top&Eproc)
                n.Diag |= n.Left.Diag
                l = n.Left
                if l.Op == ONAME && l.Etype != 0 {
 
                        n.Left = n.Right
                        n.Right = nil
-                       typecheck1(&n, top)
-                       return
+                       n = typecheck1(n, top)
+                       return n
                }
 
-               defaultlit(&n.Left, nil)
+               n.Left = defaultlit(n.Left, nil)
                l = n.Left
                if l.Op == OTYPE {
                        if n.Isddd || l.Type.Bound == -100 {
                        n.Type = l.Type
                        if !onearg(n, "conversion to %v", l.Type) {
                                n.Type = nil
-                               return
+                               return n
                        }
-                       typecheck1(&n, top)
-                       return
+                       n = typecheck1(n, top)
+                       return n
                }
 
                if n.List.Len() == 1 && !n.Isddd {
-                       typecheck(n.List.Addr(0), Erv|Efnstruct)
+                       n.List.SetIndex(0, typecheck(n.List.Index(0), Erv|Efnstruct))
                } else {
                        typecheckslice(n.List.Slice(), Erv)
                }
                t := l.Type
                if t == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                checkwidth(t)
 
                        if t.Etype != TFUNC {
                                Yyerror("cannot call non-function %v (type %v)", l, t)
                                n.Type = nil
-                               return
+                               return n
                        }
                }
 
                ok |= Erv
                if !onearg(n, "%v", Oconv(n.Op, 0)) {
                        n.Type = nil
-                       return
+                       return n
                }
-               typecheck(&n.Left, Erv)
-               defaultlit(&n.Left, nil)
-               implicitstar(&n.Left)
+               n.Left = typecheck(n.Left, Erv)
+               n.Left = defaultlit(n.Left, nil)
+               n.Left = implicitstar(n.Left)
                l := n.Left
                t := l.Type
                if t == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                switch n.Op {
                case OCAP:
        badcall1:
                Yyerror("invalid argument %v for %v", Nconv(n.Left, FmtLong), Oconv(n.Op, 0))
                n.Type = nil
-               return
+               return n
 
        case OCOMPLEX:
                ok |= Erv
                        if n.List.First().Op != OCALLFUNC && n.List.First().Op != OCALLMETH {
                                Yyerror("invalid operation: complex expects two arguments")
                                n.Type = nil
-                               return
+                               return n
                        }
 
                        t := n.List.First().Left.Type
                        if t.Results().NumFields() != 2 {
                                Yyerror("invalid operation: complex expects two arguments, %v returns %d results", n.List.First(), t.Results().NumFields())
                                n.Type = nil
-                               return
+                               return n
                        }
 
                        t = n.List.First().Type
                } else {
                        if !twoarg(n) {
                                n.Type = nil
-                               return
+                               return n
                        }
-                       l = typecheck(&n.Left, Erv|top&Eiota)
-                       r = typecheck(&n.Right, Erv|top&Eiota)
+                       n.Left = typecheck(n.Left, Erv|top&Eiota)
+                       n.Right = typecheck(n.Right, Erv|top&Eiota)
+                       l = n.Left
+                       r = n.Right
                        if l.Type == nil || r.Type == nil {
                                n.Type = nil
-                               return
+                               return n
                        }
-                       defaultlit2(&l, &r, false)
+                       l, r = defaultlit2(l, r, false)
                        if l.Type == nil || r.Type == nil {
                                n.Type = nil
-                               return
+                               return n
                        }
                        n.Left = l
                        n.Right = r
                if !Eqtype(l.Type, r.Type) {
                        Yyerror("invalid operation: %v (mismatched types %v and %v)", n, l.Type, r.Type)
                        n.Type = nil
-                       return
+                       return n
                }
 
                var t *Type
                default:
                        Yyerror("invalid operation: %v (arguments have type %v, expected floating-point)", n, l.Type)
                        n.Type = nil
-                       return
+                       return n
 
                case TIDEAL:
                        t = Types[TIDEAL]
        case OCLOSE:
                if !onearg(n, "%v", Oconv(n.Op, 0)) {
                        n.Type = nil
-                       return
+                       return n
                }
-               typecheck(&n.Left, Erv)
-               defaultlit(&n.Left, nil)
+               n.Left = typecheck(n.Left, Erv)
+               n.Left = defaultlit(n.Left, nil)
                l := n.Left
                t := l.Type
                if t == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                if t.Etype != TCHAN {
                        Yyerror("invalid operation: %v (non-chan type %v)", n, t)
                        n.Type = nil
-                       return
+                       return n
                }
 
                if t.Chan&Csend == 0 {
                        Yyerror("invalid operation: %v (cannot close receive-only channel)", n)
                        n.Type = nil
-                       return
+                       return n
                }
 
                ok |= Etop
                if args.Len() == 0 {
                        Yyerror("missing arguments to delete")
                        n.Type = nil
-                       return
+                       return n
                }
 
                if args.Len() == 1 {
                        Yyerror("missing second (key) argument to delete")
                        n.Type = nil
-                       return
+                       return n
                }
 
                if args.Len() != 2 {
                        Yyerror("too many arguments to delete")
                        n.Type = nil
-                       return
+                       return n
                }
 
                ok |= Etop
                if l.Type != nil && l.Type.Etype != TMAP {
                        Yyerror("first argument to delete must be map; have %v", Tconv(l.Type, FmtLong))
                        n.Type = nil
-                       return
+                       return n
                }
 
                args.SetIndex(1, assignconv(r, l.Type.Key(), "delete"))
                if args.Len() == 0 {
                        Yyerror("missing arguments to append")
                        n.Type = nil
-                       return
+                       return n
                }
 
                if args.Len() == 1 && !n.Isddd {
-                       typecheck(args.Addr(0), Erv|Efnstruct)
+                       args.SetIndex(0, typecheck(args.Index(0), Erv|Efnstruct))
                } else {
                        typecheckslice(args.Slice(), Erv)
                }
                t := args.First().Type
                if t == nil {
                        n.Type = nil
-                       return
+                       return n
                }
 
                // Unpack multiple-return result before type-checking.
                        if Isconst(args.First(), CTNIL) {
                                Yyerror("first argument to append must be typed slice; have untyped nil")
                                n.Type = nil
-                               return
+                               return n
                        }
 
                        Yyerror("first argument to append must be slice; have %v", Tconv(t, FmtLong))
                        n.Type = nil
-                       return
+                       return n
                }
 
                if n.Isddd {
                        if args.Len() == 1 {
                                Yyerror("cannot use ... on first argument to append")
                                n.Type = nil
-                               return
+                               return n
                        }
 
                        if args.Len() != 2 {
                                Yyerror("too many arguments to append")
                                n.Type = nil
-                               return
+                               return n
                        }
 
                        if Istype(t.Type, TUINT8) && Istype(args.Second().Type, TSTRING) {
-                               defaultlit(args.Addr(1), Types[TSTRING])
+                               args.SetIndex(1, defaultlit(args.Index(1), Types[TSTRING]))
                                break OpSwitch
                        }
 
                if args.Len() < 2 {
                        Yyerror("missing arguments to copy")
                        n.Type = nil
-                       return
+                       return n
                }
 
                if args.Len() > 2 {
                        Yyerror("too many arguments to copy")
                        n.Type = nil
-                       return
+                       return n
                }
 
                n.Left = args.First()
                n.Right = args.Second()
                n.List.Set(nil)
                n.Type = Types[TINT]
-               typecheck(&n.Left, Erv)
-               typecheck(&n.Right, Erv)
+               n.Left = typecheck(n.Left, Erv)
+               n.Right = typecheck(n.Right, Erv)
                if n.Left.Type == nil || n.Right.Type == nil {
                        n.Type = nil
-                       return
+                       return n
                }
-               defaultlit(&n.Left, nil)
-               defaultlit(&n.Right, nil)
+               n.Left = defaultlit(n.Left, nil)
+               n.Right = defaultlit(n.Right, nil)
                if n.Left.Type == nil || n.Right.Type == nil {
                        n.Type = nil
-                       return
+                       return n
                }
 
                // copy([]byte, string)
                        }
                        Yyerror("arguments to copy have different element types: %v and string", Tconv(n.Left.Type, FmtLong))
                        n.Type = nil
-                       return
+                       return n
                }
 
                if !Isslice(n.Left.Type) || !Isslice(n.Right.Type) {
                                Yyerror("second argument to copy should be slice or string; have %v", Tconv(n.Right.Type, FmtLong))
                        }
                        n.Type = nil
-                       return
+                       return n
                }
 
                if !Eqtype(n.Left.Type.Type, n.Right.Type.Type) {
                        Yyerror("arguments to copy have different element types: %v and %v", Tconv(n.Left.Type, FmtLong), Tconv(n.Right.Type, FmtLong))
                        n.Type = nil
-                       return
+                       return n
                }
 
                break OpSwitch
        case OCONV:
                ok |= Erv
                saveorignode(n)
-               typecheck(&n.Left, Erv|top&(Eindir|Eiota))
-               convlit1(&n.Left, n.Type, true)
+               n.Left = typecheck(n.Left, Erv|top&(Eindir|Eiota))
+               n.Left = convlit1(n.Left, n.Type, true)
                t := n.Left.Type
                if t == nil || n.Type == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                var why string
                n.Op = convertop(t, n.Type, &why)
 
                case OSTRARRAYRUNE:
                        if n.Left.Op == OLITERAL {
-                               stringtoarraylit(&n)
+                               n = stringtoarraylit(n)
                        }
                }
 
                if len(args) == 0 {
                        Yyerror("missing argument to make")
                        n.Type = nil
-                       return
+                       return n
                }
 
                n.List.Set(nil)
                l := args[0]
-               typecheck(&l, Etype)
+               l = typecheck(l, Etype)
                t := l.Type
                if t == nil {
                        n.Type = nil
-                       return
+                       return n
                }
 
                i := 1
                default:
                        Yyerror("cannot make type %v", t)
                        n.Type = nil
-                       return
+                       return n
 
                case TARRAY:
                        if !Isslice(t) {
                                Yyerror("cannot make type %v", t)
                                n.Type = nil
-                               return
+                               return n
                        }
 
                        if i >= len(args) {
                                Yyerror("missing len argument to make(%v)", t)
                                n.Type = nil
-                               return
+                               return n
                        }
 
                        l = args[i]
                        i++
-                       typecheck(&l, Erv)
+                       l = typecheck(l, Erv)
                        var r *Node
                        if i < len(args) {
                                r = args[i]
                                i++
-                               typecheck(&r, Erv)
+                               r = typecheck(r, Erv)
                        }
 
                        if l.Type == nil || (r != nil && r.Type == nil) {
                                n.Type = nil
-                               return
+                               return n
                        }
                        if !checkmake(t, "len", l) || r != nil && !checkmake(t, "cap", r) {
                                n.Type = nil
-                               return
+                               return n
                        }
                        if Isconst(l, CTINT) && r != nil && Isconst(r, CTINT) && l.Val().U.(*Mpint).Cmp(r.Val().U.(*Mpint)) > 0 {
                                Yyerror("len larger than cap in make(%v)", t)
                                n.Type = nil
-                               return
+                               return n
                        }
 
                        n.Left = l
                        if i < len(args) {
                                l = args[i]
                                i++
-                               typecheck(&l, Erv)
-                               defaultlit(&l, Types[TINT])
+                               l = typecheck(l, Erv)
+                               l = defaultlit(l, Types[TINT])
                                if l.Type == nil {
                                        n.Type = nil
-                                       return
+                                       return n
                                }
                                if !checkmake(t, "size", l) {
                                        n.Type = nil
-                                       return
+                                       return n
                                }
                                n.Left = l
                        } else {
                        if i < len(args) {
                                l = args[i]
                                i++
-                               typecheck(&l, Erv)
-                               defaultlit(&l, Types[TINT])
+                               l = typecheck(l, Erv)
+                               l = defaultlit(l, Types[TINT])
                                if l.Type == nil {
                                        n.Type = nil
-                                       return
+                                       return n
                                }
                                if !checkmake(t, "buffer", l) {
                                        n.Type = nil
-                                       return
+                                       return n
                                }
                                n.Left = l
                        } else {
                        Yyerror("too many arguments to make(%v)", t)
                        n.Op = OMAKE
                        n.Type = nil
-                       return
+                       return n
                }
 
                n.Type = t
                if args.Len() == 0 {
                        Yyerror("missing argument to new")
                        n.Type = nil
-                       return
+                       return n
                }
 
                l := args.First()
-               typecheck(&l, Etype)
+               l = typecheck(l, Etype)
                t := l.Type
                if t == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                if args.Len() > 1 {
                        Yyerror("too many arguments to new(%v)", t)
                        n.Type = nil
-                       return
+                       return n
                }
 
                n.Left = l
                for i1, n1 := range ls {
                        // Special case for print: int constant is int64, not int.
                        if Isconst(n1, CTINT) {
-                               defaultlit(&ls[i1], Types[TINT64])
+                               ls[i1] = defaultlit(ls[i1], Types[TINT64])
                        } else {
-                               defaultlit(&ls[i1], nil)
+                               ls[i1] = defaultlit(ls[i1], nil)
                        }
                }
 
                ok |= Etop
                if !onearg(n, "panic") {
                        n.Type = nil
-                       return
+                       return n
                }
-               typecheck(&n.Left, Erv)
-               defaultlit(&n.Left, Types[TINTER])
+               n.Left = typecheck(n.Left, Erv)
+               n.Left = defaultlit(n.Left, Types[TINTER])
                if n.Left.Type == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                break OpSwitch
 
                if n.List.Len() != 0 {
                        Yyerror("too many arguments to recover")
                        n.Type = nil
-                       return
+                       return n
                }
 
                n.Type = Types[TINTER]
                typecheckclosure(n, top)
                if n.Type == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                break OpSwitch
 
        case OITAB:
                ok |= Erv
-               typecheck(&n.Left, Erv)
+               n.Left = typecheck(n.Left, Erv)
                t := n.Left.Type
                if t == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                if t.Etype != TINTER {
                        Fatalf("OITAB of %v", t)
 
        case OSPTR:
                ok |= Erv
-               typecheck(&n.Left, Erv)
+               n.Left = typecheck(n.Left, Erv)
                t := n.Left.Type
                if t == nil {
                        n.Type = nil
-                       return
+                       return n
                }
                if !Isslice(t) && t.Etype != TSTRING {
                        Fatalf("OSPTR of %v", t)
 
        case OCFUNC:
                ok |= Erv
-               typecheck(&n.Left, Erv)
+               n.Left = typecheck(n.Left, Erv)
                n.Type = Types[TUINTPTR]
                break OpSwitch
 
        case OCONVNOP:
                ok |= Erv
-               typecheck(&n.Left, Erv)
+               n.Left = typecheck(n.Left, Erv)
                break OpSwitch
 
        // statements
 
        case ODEFER:
                ok |= Etop
-               typecheck(&n.Left, Etop|Erv)
+               n.Left = typecheck(n.Left, Etop|Erv)
                if n.Left.Diag == 0 {
                        checkdefergo(n)
                }
 
        case OPROC:
                ok |= Etop
-               typecheck(&n.Left, Etop|Eproc|Erv)
+               n.Left = typecheck(n.Left, Etop|Eproc|Erv)
                checkdefergo(n)
                break OpSwitch
 
                ok |= Etop
                typecheckslice(n.Ninit.Slice(), Etop)
                decldepth++
-               typecheck(&n.Left, Erv)
+               n.Left = typecheck(n.Left, Erv)
                if n.Left != nil {
                        t := n.Left.Type
                        if t != nil && t.Etype != TBOOL {
                                Yyerror("non-bool %v used as for condition", Nconv(n.Left, FmtLong))
                        }
                }
-               typecheck(&n.Right, Etop)
+               n.Right = typecheck(n.Right, Etop)
                typecheckslice(n.Nbody.Slice(), Etop)
                decldepth--
                break OpSwitch
        case OIF:
                ok |= Etop
                typecheckslice(n.Ninit.Slice(), Etop)
-               typecheck(&n.Left, Erv)
+               n.Left = typecheck(n.Left, Erv)
                if n.Left != nil {
                        t := n.Left.Type
                        if t != nil && t.Etype != TBOOL {
                if Curfn == nil {
                        Yyerror("return outside function")
                        n.Type = nil
-                       return
+                       return n
                }
 
                if Curfn.Type.Outnamed && n.List.Len() == 0 {
        case OTYPESW:
                Yyerror("use of .(type) outside type switch")
                n.Type = nil
-               return
+               return n
 
        case OXCASE:
                ok |= Etop
 
        case ODCLCONST:
                ok |= Etop
-               typecheck(&n.Left, Erv)
+               n.Left = typecheck(n.Left, Erv)
                break OpSwitch
 
        case ODCLTYPE:
                ok |= Etop
-               typecheck(&n.Left, Etype)
+               n.Left = typecheck(n.Left, Etype)
                if incannedimport == 0 {
                        checkwidth(n.Left.Type)
                }
        if n.Op == OTYPE && top&Etype == 0 {
                Yyerror("type %v is not an expression", n.Type)
                n.Type = nil
-               return
+               return n
        }
 
        if top&(Erv|Etype) == Etype && n.Op != OTYPE {
                Yyerror("%v is not a type", n)
                n.Type = nil
-               return
+               return n
        }
 
        // TODO(rsc): simplify
        if (top&(Ecall|Erv|Etype) != 0) && top&Etop == 0 && ok&(Erv|Etype|Ecall) == 0 {
                Yyerror("%v used as value", n)
                n.Type = nil
-               return
+               return n
        }
 
        if (top&Etop != 0) && top&(Ecall|Erv|Etype) == 0 && ok&Etop == 0 {
                }
 
                n.Type = nil
-               return
+               return n
        }
 
        /* TODO
        if(n->type == T)
                fatal("typecheck nil type");
        */
+       return n
 }
 
 func checksliceindex(l *Node, r *Node, tp *Type) bool {
        }
 }
 
-func implicitstar(nn **Node) {
+// The result of implicitstar MUST be assigned back to n, e.g.
+//     n.Left = implicitstar(n.Left)
+func implicitstar(n *Node) *Node {
        // insert implicit * if needed for fixed array
-       n := *nn
-
        t := n.Type
        if t == nil || !Isptr[t.Etype] {
-               return
+               return n
        }
        t = t.Type
        if t == nil {
-               return
+               return n
        }
        if !Isfixedarray(t) {
-               return
+               return n
        }
        n = Nod(OIND, n, nil)
        n.Implicit = true
-       typecheck(&n, Erv)
-       *nn = n
+       n = typecheck(n, Erv)
+       return n
 }
 
 func onearg(n *Node, f string, args ...interface{}) bool {
                        if Isptr[n.Left.Type.Etype] {
                                n.Left = Nod(OIND, n.Left, nil) // implicitstar
                                n.Left.Implicit = true
-                               typecheck(&n.Left, Erv)
+                               n.Left = typecheck(n.Left, Erv)
                        }
 
                        n.Op = ODOTINTER
                                checklvalue(n.Left, "call pointer method on")
                                n.Left = Nod(OADDR, n.Left, nil)
                                n.Left.Implicit = true
-                               typecheck(&n.Left, Etype|Erv)
+                               n.Left = typecheck(n.Left, Etype|Erv)
                        } else if tt.Etype == Tptr && rcvr.Etype != Tptr && Eqtype(tt.Type, rcvr) {
                                n.Left = Nod(OIND, n.Left, nil)
                                n.Left.Implicit = true
-                               typecheck(&n.Left, Etype|Erv)
+                               n.Left = typecheck(n.Left, Etype|Erv)
                        } else if tt.Etype == Tptr && tt.Type.Etype == Tptr && Eqtype(derefall(tt), derefall(rcvr)) {
                                Yyerror("calling method %v with receiver %v requires explicit dereference", n.Sym, Nconv(n.Left, FmtLong))
                                for tt.Etype == Tptr {
                                        }
                                        n.Left = Nod(OIND, n.Left, nil)
                                        n.Left.Implicit = true
-                                       typecheck(&n.Left, Etype|Erv)
+                                       n.Left = typecheck(n.Left, Etype|Erv)
                                        tt = tt.Type
                                }
                        } else {
                n.Implicit = true       // don't print
                n.Right.Implicit = true // * is okay
        } else if Debug['s'] != 0 {
-               typecheck(&n.Right, Etype)
+               n.Right = typecheck(n.Right, Etype)
                if n.Right.Type != nil && Eqtype(n.Right.Type, t) {
                        fmt.Printf("%v: redundant type: %v\n", n.Line(), t)
                }
 // TODO(mdempsky): Find a nicer solution.
 var structkey = typ(Txxx)
 
-func typecheckcomplit(np **Node) {
-       n := *np
+// The result of typecheckcomplit MUST be assigned back to n, e.g.
+//     n.Left = typecheckcomplit(n.Left)
+func typecheckcomplit(n *Node) *Node {
        lno := lineno
        defer func() {
                lineno = lno
-               *np = n
        }()
 
        if n.Right == nil {
                }
                Yyerror("missing type in composite literal")
                n.Type = nil
-               return
+               return n
        }
 
        // Save original node (including n->right)
        *norig = *n
 
        setlineno(n.Right)
-       l := typecheck(&n.Right, Etype|Ecomplit) // sic
+       n.Right = typecheck(n.Right, Etype|Ecomplit)
+       l := n.Right // sic
        t := l.Type
        if t == nil {
                n.Type = nil
-               return
+               return n
        }
        nerr := nerrors
        n.Type = t
                if !n.Right.Implicit {
                        Yyerror("invalid pointer type %v for composite literal (use &%v instead)", t, t.Type)
                        n.Type = nil
-                       return
+                       return n
                }
 
                // Also, the underlying type must be a struct, map, slice, or array.
                if !iscomptype(t) {
                        Yyerror("invalid pointer type %v for composite literal", t)
                        n.Type = nil
-                       return
+                       return n
                }
 
                t = t.Type
                                n.List.SetIndex(i2, l)
                        }
 
-                       typecheck(&l.Left, Erv)
+                       l.Left = typecheck(l.Left, Erv)
                        evconst(l.Left)
                        i = nonnegconst(l.Left)
                        if i < 0 && l.Left.Diag == 0 {
 
                        r = l.Right
                        pushtype(r, t.Type)
-                       typecheck(&r, Erv)
-                       defaultlit(&r, t.Type)
+                       r = typecheck(r, Erv)
+                       r = defaultlit(r, t.Type)
                        l.Right = assignconv(r, t.Type, "array or slice literal")
                }
 
                        l = n3
                        setlineno(l)
                        if l.Op != OKEY {
-                               typecheck(n.List.Addr(i3), Erv)
+                               n.List.SetIndex(i3, typecheck(n.List.Index(i3), Erv))
                                Yyerror("missing key in map literal")
                                continue
                        }
 
                        r = l.Left
                        pushtype(r, t.Key())
-                       typecheck(&r, Erv)
-                       defaultlit(&r, t.Key())
+                       r = typecheck(r, Erv)
+                       r = defaultlit(r, t.Key())
                        l.Left = assignconv(r, t.Key(), "map key")
                        if l.Left.Op != OCONV {
                                keydup(l.Left, hash)
 
                        r = l.Right
                        pushtype(r, t.Type)
-                       typecheck(&r, Erv)
-                       defaultlit(&r, t.Type)
+                       r = typecheck(r, Erv)
+                       r = defaultlit(r, t.Type)
                        l.Right = assignconv(r, t.Type, "map value")
                }
 
                        ls := n.List.Slice()
                        for i1, n1 := range ls {
                                setlineno(n1)
-                               typecheck(&ls[i1], Erv)
+                               ls[i1] = typecheck(ls[i1], Erv)
                                n1 = ls[i1]
                                if f == nil {
                                        if bad == 0 {
                                                Yyerror("mixture of field:value and value initializers")
                                        }
                                        bad++
-                                       typecheck(&ls[i], Erv)
+                                       ls[i] = typecheck(ls[i], Erv)
                                        continue
                                }
 
                                s := l.Left.Sym
                                if s == nil {
                                        Yyerror("invalid field name %v in struct initializer", l.Left)
-                                       typecheck(&l.Right, Erv)
+                                       l.Right = typecheck(l.Right, Erv)
                                        continue
                                }
 
                                r = l.Right
 
                                // No pushtype allowed here. Tried and rejected.
-                               typecheck(&r, Erv)
+                               r = typecheck(r, Erv)
 
                                l.Right = assignconv(r, f.Type, "field value")
                        }
 
        if nerr != nerrors {
                n.Type = nil
-               return
+               return n
        }
 
        n.Orig = norig
        }
 
        n.Orig = norig
-       return
+       return n
 }
 
 // lvalue etc
        n.Left = resolve(n.Left)
 
        if n.Left.Name == nil || n.Left.Name.Defn != n || n.Left.Name.Param.Ntype != nil {
-               typecheck(&n.Left, Erv|Easgn)
+               n.Left = typecheck(n.Left, Erv|Easgn)
        }
 
-       typecheck(&n.Right, Erv)
+       n.Right = typecheck(n.Right, Erv)
        checkassign(n, n.Left)
        if n.Right != nil && n.Right.Type != nil {
                if n.Left.Type != nil {
        }
 
        if n.Left.Name != nil && n.Left.Name.Defn == n && n.Left.Name.Param.Ntype == nil {
-               defaultlit(&n.Right, nil)
+               n.Right = defaultlit(n.Right, nil)
                n.Left.Type = n.Right.Type
        }
 
        n.Typecheck = 1
 
        if n.Left.Typecheck == 0 {
-               typecheck(&n.Left, Erv|Easgn)
+               n.Left = typecheck(n.Left, Erv|Easgn)
        }
 }
 
                ls[i1] = n1
 
                if n1.Name == nil || n1.Name.Defn != n || n1.Name.Param.Ntype != nil {
-                       typecheck(&ls[i1], Erv|Easgn)
+                       ls[i1] = typecheck(ls[i1], Erv|Easgn)
                }
        }
 
        cl := n.List.Len()
        cr := n.Rlist.Len()
        if cl > 1 && cr == 1 {
-               typecheck(n.Rlist.Addr(0), Erv|Efnstruct)
+               n.Rlist.SetIndex(0, typecheck(n.Rlist.Index(0), Erv|Efnstruct))
        } else {
                typecheckslice(n.Rlist.Slice(), Erv)
        }
                                rs[il] = assignconv(nr, nl.Type, "assignment")
                        }
                        if nl.Name != nil && nl.Name.Defn == n && nl.Name.Param.Ntype == nil {
-                               defaultlit(&rs[il], nil)
+                               rs[il] = defaultlit(rs[il], nil)
                                nl.Type = rs[il].Type
                        }
                }
        ls = n.List.Slice()
        for i1, n1 := range ls {
                if n1.Typecheck == 0 {
-                       typecheck(&ls[i1], Erv|Easgn)
+                       ls[i1] = typecheck(ls[i1], Erv|Easgn)
                }
        }
 }
 
 // type check function definition
 func typecheckfunc(n *Node) {
-       typecheck(&n.Func.Nname, Erv|Easgn)
+       n.Func.Nname = typecheck(n.Func.Nname, Erv|Easgn)
        t := n.Func.Nname.Type
        if t == nil {
                return
        }
 }
 
-func stringtoarraylit(np **Node) {
-       n := *np
+// The result of stringtoarraylit MUST be assigned back to n, e.g.
+//     n.Left = stringtoarraylit(n.Left)
+func stringtoarraylit(n *Node) *Node {
        if n.Left.Op != OLITERAL || n.Left.Val().Ctype() != CTSTR {
                Fatalf("stringtoarraylit %v", n)
        }
 
        nn := Nod(OCOMPLIT, nil, typenod(n.Type))
        nn.List.Set(l)
-       typecheck(&nn, Erv)
-       *np = nn
+       nn = typecheck(nn, Erv)
+       return nn
 }
 
 var ntypecheckdeftype int
 
 func domethod(n *Node) {
        nt := n.Type.Nname
-       typecheck(&nt, Etype)
+       nt = typecheck(nt, Etype)
        if nt.Type == nil {
                // type check failed; leave empty func
                // TODO(mdempsky): Fix Type rekinding.
        setlineno(n)
        n.Type.Sym = n.Sym
        n.Typecheck = 1
-       typecheck(&n.Name.Param.Ntype, Etype)
+       n.Name.Param.Ntype = typecheck(n.Name.Param.Ntype, Etype)
        t := n.Name.Param.Ntype.Type
        if t == nil {
                n.Diag = 1
 
        case OLITERAL:
                if n.Name.Param.Ntype != nil {
-                       typecheck(&n.Name.Param.Ntype, Etype)
+                       n.Name.Param.Ntype = typecheck(n.Name.Param.Ntype, Etype)
                        n.Type = n.Name.Param.Ntype.Type
                        n.Name.Param.Ntype = nil
                        if n.Type == nil {
                        Yyerror("xxx")
                }
 
-               typecheck(&e, Erv|Eiota)
+               e = typecheck(e, Erv|Eiota)
                if Isconst(e, CTNIL) {
                        Yyerror("const initializer cannot be nil")
                        goto ret
                                goto ret
                        }
 
-                       convlit(&e, t)
+                       e = convlit(e, t)
                }
 
                n.SetVal(e.Val())
 
        case ONAME:
                if n.Name.Param.Ntype != nil {
-                       typecheck(&n.Name.Param.Ntype, Etype)
+                       n.Name.Param.Ntype = typecheck(n.Name.Param.Ntype, Etype)
                        n.Type = n.Name.Param.Ntype.Type
                        if n.Type == nil {
                                n.Diag = 1
                }
 
                if n.Name.Defn.Op == ONAME {
-                       typecheck(&n.Name.Defn, Erv)
+                       n.Name.Defn = typecheck(n.Name.Defn, Erv)
                        n.Type = n.Name.Defn.Type
                        break
                }
 
-               typecheck(&n.Name.Defn, Etop) // fills in n->type
+               n.Name.Defn = typecheck(n.Name.Defn, Etop) // fills in n->type
 
        case OTYPE:
                if Curfn != nil {
 
                        // Delay defaultlit until after we've checked range, to avoid
                        // a redundant "constant NNN overflows int" error.
-                       defaultlit(&n, Types[TINT])
+                       n = defaultlit(n, Types[TINT])
 
                        return true
 
        }
 
        // Defaultlit still necessary for non-constant: n might be 1<<k.
-       defaultlit(&n, Types[TINT])
+       n = defaultlit(n, Types[TINT])
 
        return true
 }
 
        var v int64
        switch s.Name {
        case "Alignof", "Sizeof":
-               typecheck(&r, Erv)
-               defaultlit(&r, nil)
+               r = typecheck(r, Erv)
+               r = defaultlit(r, nil)
                tr := r.Type
                if tr == nil {
                        goto bad
                // Remember base of selector to find it back after dot insertion.
                // Since r->left may be mutated by typechecking, check it explicitly
                // first to track it correctly.
-               typecheck(&r.Left, Erv)
+               r.Left = typecheck(r.Left, Erv)
                base := r.Left
 
-               typecheck(&r, Erv)
+               r = typecheck(r, Erv)
                switch r.Op {
                case ODOT, ODOTPTR:
                        break
 
        // It's hard to be on the heap when not-used, but best to be consistent about &~PHEAP here and below.
        for i, ln := range fn.Func.Dcl {
                if ln.Op == ONAME && ln.Class&^PHEAP == PAUTO {
-                       typecheck(&ln, Erv|Easgn)
+                       ln = typecheck(ln, Erv|Easgn)
                        fn.Func.Dcl[i] = ln
                }
        }
 
 func walkstmtlist(s []*Node) {
        for i := range s {
-               walkstmt(&s[i])
+               s[i] = walkstmt(s[i])
        }
 }
 
        }
 }
 
-func walkstmt(np **Node) {
-       n := *np
+// The result of walkstmt MUST be assigned back to n, e.g.
+//     n.Left = walkstmt(n.Left)
+func walkstmt(n *Node) *Node {
        if n == nil {
-               return
+               return n
        }
        if n.Dodata == 2 { // don't walk, generated by anylit.
-               return
+               return n
        }
 
        setlineno(n)
                if n.Typecheck == 0 {
                        Fatalf("missing typecheck: %v", Nconv(n, FmtSign))
                }
+               wascopy := n.Op == OCOPY
                init := n.Ninit
                n.Ninit.Set(nil)
-               walkexpr(&n, &init)
-               addinit(&n, init.Slice())
-               if (*np).Op == OCOPY && n.Op == OCONVNOP {
+               n = walkexpr(n, &init)
+               n = addinit(n, init.Slice())
+               if wascopy && n.Op == OCONVNOP {
                        n.Op = OEMPTY // don't leave plain values as statements.
                }
 
                init := n.Ninit
                n.Ninit.Set(nil)
 
-               walkexpr(&n.Left, &init)
+               n.Left = walkexpr(n.Left, &init)
                n = mkcall1(chanfn("chanrecv1", 2, n.Left.Type), nil, &init, typename(n.Left.Type), n.Left, nodnil())
-               walkexpr(&n, &init)
+               n = walkexpr(n, &init)
 
-               addinit(&n, init.Slice())
+               n = addinit(n, init.Slice())
 
        case OBREAK,
                ODCL,
                fallthrough
 
        case OCASE:
-               walkstmt(&n.Right)
+               n.Right = walkstmt(n.Right)
 
        case ODEFER:
                hasdefer = true
                switch n.Left.Op {
                case OPRINT, OPRINTN:
-                       walkprintfunc(&n.Left, &n.Ninit)
+                       n.Left = walkprintfunc(n.Left, &n.Ninit)
 
                case OCOPY:
                        n.Left = copyany(n.Left, &n.Ninit, true)
 
                default:
-                       walkexpr(&n.Left, &n.Ninit)
+                       n.Left = walkexpr(n.Left, &n.Ninit)
                }
 
                // make room for size & fn arguments.
                        walkstmtlist(n.Left.Ninit.Slice())
                        init := n.Left.Ninit
                        n.Left.Ninit.Set(nil)
-                       walkexpr(&n.Left, &init)
-                       addinit(&n.Left, init.Slice())
+                       n.Left = walkexpr(n.Left, &init)
+                       n.Left = addinit(n.Left, init.Slice())
                }
 
-               walkstmt(&n.Right)
+               n.Right = walkstmt(n.Right)
                walkstmtlist(n.Nbody.Slice())
 
        case OIF:
-               walkexpr(&n.Left, &n.Ninit)
+               n.Left = walkexpr(n.Left, &n.Ninit)
                walkstmtlist(n.Nbody.Slice())
                walkstmtlist(n.Rlist.Slice())
 
        case OPROC:
                switch n.Left.Op {
                case OPRINT, OPRINTN:
-                       walkprintfunc(&n.Left, &n.Ninit)
+                       n.Left = walkprintfunc(n.Left, &n.Ninit)
 
                case OCOPY:
                        n.Left = copyany(n.Left, &n.Ninit, true)
 
                default:
-                       walkexpr(&n.Left, &n.Ninit)
+                       n.Left = walkexpr(n.Left, &n.Ninit)
                }
 
                // make room for size & fn arguments.
        if n.Op == ONAME {
                Fatalf("walkstmt ended up with name: %v", Nconv(n, FmtSign))
        }
-
-       *np = n
+       return n
 }
 
 func isSmallMakeSlice(n *Node) bool {
 // complex side effects like statements are appended to init
 func walkexprlist(s []*Node, init *Nodes) {
        for i := range s {
-               walkexpr(&s[i], init)
+               s[i] = walkexpr(s[i], init)
        }
 }
 
 func walkexprlistsafe(s []*Node, init *Nodes) {
        for i, n := range s {
                s[i] = safeexpr(n, init)
-               walkexpr(&s[i], init)
+               s[i] = walkexpr(s[i], init)
        }
 }
 
 func walkexprlistcheap(s []*Node, init *Nodes) {
        for i, n := range s {
                s[i] = cheapexpr(n, init)
-               walkexpr(&s[i], init)
+               s[i] = walkexpr(s[i], init)
        }
 }
 
        panic("unreachable")
 }
 
-func walkexpr(np **Node, init *Nodes) {
-       n := *np
-
+// The result of walkexpr MUST be assigned back to n, e.g.
+//     n.Left = walkexpr(n.Left, init)
+func walkexpr(n *Node, init *Nodes) *Node {
        if n == nil {
-               return
+               return n
        }
 
        if init == &n.Ninit {
 
        // annoying case - not typechecked
        if n.Op == OKEY {
-               walkexpr(&n.Left, init)
-               walkexpr(&n.Right, init)
-               return
+               n.Left = walkexpr(n.Left, init)
+               n.Right = walkexpr(n.Right, init)
+               return n
        }
 
        lno := setlineno(n)
                OIMAG,
                ODOTMETH,
                ODOTINTER:
-               walkexpr(&n.Left, init)
+               n.Left = walkexpr(n.Left, init)
 
        case OIND:
-               walkexpr(&n.Left, init)
+               n.Left = walkexpr(n.Left, init)
 
        case ODOT:
                usefield(n)
-               walkexpr(&n.Left, init)
+               n.Left = walkexpr(n.Left, init)
 
        case ODOTPTR:
                usefield(n)
                        checknil(n.Left, init)
                }
 
-               walkexpr(&n.Left, init)
+               n.Left = walkexpr(n.Left, init)
 
        case OEFACE:
-               walkexpr(&n.Left, init)
-               walkexpr(&n.Right, init)
+               n.Left = walkexpr(n.Left, init)
+               n.Right = walkexpr(n.Right, init)
 
        case OSPTR, OITAB:
-               walkexpr(&n.Left, init)
+               n.Left = walkexpr(n.Left, init)
 
        case OLEN, OCAP:
-               walkexpr(&n.Left, init)
+               n.Left = walkexpr(n.Left, init)
 
                // replace len(*[10]int) with 10.
                // delayed until now to preserve side effects.
                }
 
        case OLSH, ORSH:
-               walkexpr(&n.Left, init)
-               walkexpr(&n.Right, init)
+               n.Left = walkexpr(n.Left, init)
+               n.Right = walkexpr(n.Right, init)
                t := n.Left.Type
                n.Bounded = bounded(n.Right, 8*t.Width)
                if Debug['m'] != 0 && n.Etype != 0 && !Isconst(n.Right, CTINT) {
                        n.Right = n.List.Second()
                }
 
-               walkexpr(&n.Left, init)
-               walkexpr(&n.Right, init)
+               n.Left = walkexpr(n.Left, init)
+               n.Right = walkexpr(n.Right, init)
 
        case OOR, OXOR:
-               walkexpr(&n.Left, init)
-               walkexpr(&n.Right, init)
-               walkrotate(&n)
+               n.Left = walkexpr(n.Left, init)
+               n.Right = walkexpr(n.Right, init)
+               n = walkrotate(n)
 
        case OEQ, ONE:
-               walkexpr(&n.Left, init)
-               walkexpr(&n.Right, init)
+               n.Left = walkexpr(n.Left, init)
+               n.Right = walkexpr(n.Right, init)
 
                // Disable safemode while compiling this code: the code we
                // generate internally can refer to unsafe.Pointer.
                old_safemode := safemode
 
                safemode = 0
-               walkcompare(&n, init)
+               n = walkcompare(n, init)
                safemode = old_safemode
 
        case OANDAND, OOROR:
-               walkexpr(&n.Left, init)
+               n.Left = walkexpr(n.Left, init)
 
                // cannot put side effects from n.Right on init,
                // because they cannot run before n.Left is checked.
                // save elsewhere and store on the eventual n.Right.
                var ll Nodes
 
-               walkexpr(&n.Right, &ll)
-               addinit(&n.Right, ll.Slice())
+               n.Right = walkexpr(n.Right, &ll)
+               n.Right = addinit(n.Right, ll.Slice())
 
        case OPRINT, OPRINTN:
                walkexprlist(n.List.Slice(), init)
                if n.List.Len() != 0 && n.List.First().Op == OAS {
                        break
                }
-               walkexpr(&n.Left, init)
+               n.Left = walkexpr(n.Left, init)
                walkexprlist(n.List.Slice(), init)
                ll := ascompatte(n.Op, n, n.Isddd, t.Params(), n.List.Slice(), 0, init)
                n.List.Set(reorder1(ll))
                        break
                }
 
-               walkexpr(&n.Left, init)
+               n.Left = walkexpr(n.Left, init)
                walkexprlist(n.List.Slice(), init)
 
                if n.Left.Op == ONAME && n.Left.Sym.Name == "Sqrt" && n.Left.Sym.Pkg.Path == "math" {
                if n.List.Len() != 0 && n.List.First().Op == OAS {
                        break
                }
-               walkexpr(&n.Left, init)
+               n.Left = walkexpr(n.Left, init)
                walkexprlist(n.List.Slice(), init)
                ll := ascompatte(n.Op, n, false, t.Recvs(), []*Node{n.Left.Left}, 0, init)
                lr := ascompatte(n.Op, n, n.Isddd, t.Params(), n.List.Slice(), 0, init)
        case OAS:
                init.AppendNodes(&n.Ninit)
 
-               walkexpr(&n.Left, init)
+               n.Left = walkexpr(n.Left, init)
                n.Left = safeexpr(n.Left, init)
 
                if oaslit(n, init) {
 
                switch n.Right.Op {
                default:
-                       walkexpr(&n.Right, init)
+                       n.Right = walkexpr(n.Right, init)
 
                case ODOTTYPE:
                        // TODO(rsc): The Isfat is for consistency with componentgen and orderexpr.
                        // That would allow inlining x.(struct{*int}) the same as x.(*int).
                        if isdirectiface(n.Right.Type) && !Isfat(n.Right.Type) && !instrumenting {
                                // handled directly during cgen
-                               walkexpr(&n.Right, init)
+                               n.Right = walkexpr(n.Right, init)
                                break
                        }
 
                        // x = i.(T); n.Left is x, n.Right.Left is i.
                        // orderstmt made sure x is addressable.
-                       walkexpr(&n.Right.Left, init)
+                       n.Right.Left = walkexpr(n.Right.Left, init)
 
                        n1 := Nod(OADDR, n.Left, nil)
                        r := n.Right // i.(T)
                        }
 
                        fn := syslook(assertFuncName(r.Left.Type, r.Type, false))
-                       substArgTypes(&fn, r.Left.Type, r.Type)
+                       fn = substArgTypes(fn, r.Left.Type, r.Type)
 
                        n = mkcall1(fn, nil, init, typename(r.Type), r.Left, n1)
-                       walkexpr(&n, init)
+                       n = walkexpr(n, init)
                        break opswitch
 
                case ORECV:
                        // x = <-c; n.Left is x, n.Right.Left is c.
                        // orderstmt made sure x is addressable.
-                       walkexpr(&n.Right.Left, init)
+                       n.Right.Left = walkexpr(n.Right.Left, init)
 
                        n1 := Nod(OADDR, n.Left, nil)
                        r := n.Right.Left // the channel
                        n = mkcall1(chanfn("chanrecv1", 2, r.Type), nil, init, typename(r.Type), r, n1)
-                       walkexpr(&n, init)
+                       n = walkexpr(n, init)
                        break opswitch
 
                case OAPPEND:
 
                r := n.Rlist.First()
                walkexprlistsafe(n.List.Slice(), init)
-               walkexpr(&r, init)
+               r = walkexpr(r, init)
 
                ll := ascompatet(n.Op, n.List, r.Type, 0, init)
                for i, n := range ll {
 
                r := n.Rlist.First()
                walkexprlistsafe(n.List.Slice(), init)
-               walkexpr(&r.Left, init)
+               r.Left = walkexpr(r.Left, init)
                var n1 *Node
                if isblank(n.List.First()) {
                        n1 = nodnil()
                fn := chanfn("chanrecv2", 2, r.Left.Type)
                r = mkcall1(fn, n.List.Second().Type, init, typename(r.Left.Type), r.Left, n1)
                n = Nod(OAS, n.List.Second(), r)
-               typecheck(&n, Etop)
+               n = typecheck(n, Etop)
 
                // a,b = m[i];
        case OAS2MAPR:
 
                r := n.Rlist.First()
                walkexprlistsafe(n.List.Slice(), init)
-               walkexpr(&r.Left, init)
-               walkexpr(&r.Right, init)
+               r.Left = walkexpr(r.Left, init)
+               r.Right = walkexpr(r.Right, init)
                t := r.Left.Type
                p := ""
                if t.Type.Width <= 128 { // Check ../../runtime/hashmap.go:maxValueSize before changing.
                        var_ := temp(Ptrto(t.Type))
                        var_.Typecheck = 1
                        n.List.SetIndex(0, var_)
-                       walkexpr(&n, init)
+                       n = walkexpr(n, init)
                        init.Append(n)
                        n = Nod(OAS, a, Nod(OIND, var_, nil))
                }
 
-               typecheck(&n, Etop)
-               walkexpr(&n, init)
+               n = typecheck(n, Etop)
+               n = walkexpr(n, init)
 
                // TODO: ptr is always non-nil, so disable nil check for this OIND op.
 
                init.AppendNodes(&n.Ninit)
                map_ := n.List.First()
                key := n.List.Second()
-               walkexpr(&map_, init)
-               walkexpr(&key, init)
+               map_ = walkexpr(map_, init)
+               key = walkexpr(key, init)
 
                // orderstmt made sure key is addressable.
                key = Nod(OADDR, key, nil)
                if isdirectiface(e.Type) && !Isfat(e.Type) && !instrumenting {
                        // handled directly during gen.
                        walkexprlistsafe(n.List.Slice(), init)
-                       walkexpr(&e.Left, init)
+                       e.Left = walkexpr(e.Left, init)
                        break
                }
 
                init.AppendNodes(&n.Ninit)
 
                walkexprlistsafe(n.List.Slice(), init)
-               walkexpr(&e.Left, init)
+               e.Left = walkexpr(e.Left, init)
                t := e.Type    // T
                from := e.Left // i
 
                                        Warn("type assertion (ok only) inlined")
                                }
                                n = Nod(OAS, ok, fast)
-                               typecheck(&n, Etop)
+                               n = typecheck(n, Etop)
                                break
                        }
                }
                        Warn("type assertion not inlined")
                }
                fn := syslook(assertFuncName(from.Type, t, true))
-               substArgTypes(&fn, from.Type, t)
+               fn = substArgTypes(fn, from.Type, t)
                call := mkcall1(fn, oktype, init, typename(t), from, resptr)
                n = Nod(OAS, ok, call)
-               typecheck(&n, Etop)
+               n = typecheck(n, Etop)
 
        case ODOTTYPE, ODOTTYPE2:
                if !isdirectiface(n.Type) || Isfat(n.Type) {
                        Fatalf("walkexpr ODOTTYPE") // should see inside OAS only
                }
-               walkexpr(&n.Left, init)
+               n.Left = walkexpr(n.Left, init)
 
        case OCONVIFACE:
-               walkexpr(&n.Left, init)
+               n.Left = walkexpr(n.Left, init)
 
                // Optimize convT2E as a two-word copy when T is pointer-shaped.
                if isnilinter(n.Type) && isdirectiface(n.Left.Type) {
                                l := temp(Ptrto(Types[TUINT8]))
 
                                n1 := Nod(OAS, l, sym.Def)
-                               typecheck(&n1, Etop)
+                               n1 = typecheck(n1, Etop)
                                init.Append(n1)
 
                                fn := syslook("typ2Itab")
                                n1 = Nod(OCALL, fn, nil)
                                n1.List.Set(ll)
-                               typecheck(&n1, Erv)
-                               walkexpr(&n1, init)
+                               n1 = typecheck(n1, Erv)
+                               n1 = walkexpr(n1, init)
 
                                n2 := Nod(OIF, nil, nil)
                                n2.Left = Nod(OEQ, l, nodnil())
                                n2.Nbody.Set1(Nod(OAS, l, n1))
                                n2.Likely = -1
-                               typecheck(&n2, Etop)
+                               n2 = typecheck(n2, Etop)
                                init.Append(n2)
 
                                l = Nod(OEFACE, l, n.Left)
                                // Allocate stack buffer for value stored in interface.
                                r = temp(n.Left.Type)
                                r = Nod(OAS, r, nil) // zero temp
-                               typecheck(&r, Etop)
+                               r = typecheck(r, Etop)
                                init.Append(r)
                                r = Nod(OADDR, r.Left, nil)
-                               typecheck(&r, Erv)
+                               r = typecheck(r, Erv)
                        }
                        ll = append(ll, r)
                }
 
                fn := syslook(convFuncName(n.Left.Type, n.Type))
                if !Isinter(n.Left.Type) {
-                       substArgTypes(&fn, n.Left.Type, n.Left.Type, n.Type)
+                       fn = substArgTypes(fn, n.Left.Type, n.Left.Type, n.Type)
                } else {
-                       substArgTypes(&fn, n.Left.Type, n.Type)
+                       fn = substArgTypes(fn, n.Left.Type, n.Type)
                }
                dowidth(fn.Type)
                n = Nod(OCALL, fn, nil)
                n.List.Set(ll)
-               typecheck(&n, Erv)
-               walkexpr(&n, init)
+               n = typecheck(n, Erv)
+               n = walkexpr(n, init)
 
        case OCONV, OCONVNOP:
                if Thearch.Thechar == '5' {
                        }
                }
 
-               walkexpr(&n.Left, init)
+               n.Left = walkexpr(n.Left, init)
 
        case OANDNOT:
-               walkexpr(&n.Left, init)
+               n.Left = walkexpr(n.Left, init)
                n.Op = OAND
                n.Right = Nod(OCOM, n.Right, nil)
-               typecheck(&n.Right, Erv)
-               walkexpr(&n.Right, init)
+               n.Right = typecheck(n.Right, Erv)
+               n.Right = walkexpr(n.Right, init)
 
        case OMUL:
-               walkexpr(&n.Left, init)
-               walkexpr(&n.Right, init)
-               walkmul(&n, init)
+               n.Left = walkexpr(n.Left, init)
+               n.Right = walkexpr(n.Right, init)
+               n = walkmul(n, init)
 
        case ODIV, OMOD:
-               walkexpr(&n.Left, init)
-               walkexpr(&n.Right, init)
+               n.Left = walkexpr(n.Left, init)
+               n.Right = walkexpr(n.Right, init)
 
                // rewrite complex div into function call.
                et := n.Left.Type.Etype
                }
 
                // Try rewriting as shifts or magic multiplies.
-               walkdiv(&n, init)
+               n = walkdiv(n, init)
 
                // rewrite 64-bit div and mod into function calls
                // on 32-bit architectures.
                }
 
        case OINDEX:
-               walkexpr(&n.Left, init)
+               n.Left = walkexpr(n.Left, init)
 
                // save the original node for bounds checking elision.
                // If it was a ODIV/OMOD walk might rewrite it.
                r := n.Right
 
-               walkexpr(&n.Right, init)
+               n.Right = walkexpr(n.Right, init)
 
                // if range of type cannot exceed static array bound,
                // disable bounds check.
                if n.Etype == 1 {
                        break
                }
-               walkexpr(&n.Left, init)
-               walkexpr(&n.Right, init)
+               n.Left = walkexpr(n.Left, init)
+               n.Right = walkexpr(n.Right, init)
 
                t := n.Left.Type
                p := ""
                Fatalf("walkexpr ORECV") // should see inside OAS only
 
        case OSLICE, OSLICEARR, OSLICESTR:
-               walkexpr(&n.Left, init)
-               walkexpr(&n.Right.Left, init)
+               n.Left = walkexpr(n.Left, init)
+               n.Right.Left = walkexpr(n.Right.Left, init)
                if n.Right.Left != nil && iszero(n.Right.Left) {
                        // Reduce x[0:j] to x[:j].
                        n.Right.Left = nil
                }
-               walkexpr(&n.Right.Right, init)
+               n.Right.Right = walkexpr(n.Right.Right, init)
                n = reduceSlice(n)
 
        case OSLICE3, OSLICE3ARR:
-               walkexpr(&n.Left, init)
-               walkexpr(&n.Right.Left, init)
+               n.Left = walkexpr(n.Left, init)
+               n.Right.Left = walkexpr(n.Right.Left, init)
                if n.Right.Left != nil && iszero(n.Right.Left) {
                        // Reduce x[0:j:k] to x[:j:k].
                        n.Right.Left = nil
                }
-               walkexpr(&n.Right.Right.Left, init)
-               walkexpr(&n.Right.Right.Right, init)
+               n.Right.Right.Left = walkexpr(n.Right.Right.Left, init)
+               n.Right.Right.Right = walkexpr(n.Right.Right.Right, init)
 
                r := n.Right.Right.Right
                if r != nil && r.Op == OCAP && samesafeexpr(n.Left, r.Left) {
                }
 
        case OADDR:
-               walkexpr(&n.Left, init)
+               n.Left = walkexpr(n.Left, init)
 
        case ONEW:
                if n.Esc == EscNone {
                        }
                        r := temp(n.Type.Type)
                        r = Nod(OAS, r, nil) // zero temp
-                       typecheck(&r, Etop)
+                       r = typecheck(r, Etop)
                        init.Append(r)
                        r = Nod(OADDR, r.Left, nil)
-                       typecheck(&r, Erv)
+                       r = typecheck(r, Erv)
                        n = r
                } else {
                        n = callnew(n.Type.Type)
                if (Isconst(n.Left, CTSTR) && len(n.Left.Val().U.(string)) == 0) || (Isconst(n.Right, CTSTR) && len(n.Right.Val().U.(string)) == 0) {
                        // TODO(marvin): Fix Node.EType type union.
                        r := Nod(Op(n.Etype), Nod(OLEN, n.Left, nil), Nod(OLEN, n.Right, nil))
-                       typecheck(&r, Erv)
-                       walkexpr(&r, init)
+                       r = typecheck(r, Erv)
+                       r = walkexpr(r, init)
                        r.Type = n.Type
                        n = r
                        break
                if (Op(n.Etype) == OEQ || Op(n.Etype) == ONE) && Isconst(n.Right, CTSTR) && n.Left.Op == OADDSTR && n.Left.List.Len() == 2 && Isconst(n.Left.List.Second(), CTSTR) && strlit(n.Right) == strlit(n.Left.List.Second()) {
                        // TODO(marvin): Fix Node.EType type union.
                        r := Nod(Op(n.Etype), Nod(OLEN, n.Left.List.First(), nil), Nodintconst(0))
-                       typecheck(&r, Erv)
-                       walkexpr(&r, init)
+                       r = typecheck(r, Erv)
+                       r = walkexpr(r, init)
                        r.Type = n.Type
                        n = r
                        break
                                r = Nod(OOROR, Nod(ONE, Nod(OLEN, n.Left, nil), Nod(OLEN, n.Right, nil)), r)
                        }
 
-                       typecheck(&r, Erv)
-                       walkexpr(&r, nil)
+                       r = typecheck(r, Erv)
+                       r = walkexpr(r, nil)
                } else {
                        // sys_cmpstring(s1, s2) :: 0
                        r = mkcall("cmpstring", Types[TINT], init, conv(n.Left, Types[TSTRING]), conv(n.Right, Types[TSTRING]))
                        r = Nod(Op(n.Etype), r, Nodintconst(0))
                }
 
-               typecheck(&r, Erv)
+               r = typecheck(r, Erv)
                if n.Type.Etype != TBOOL {
                        Fatalf("cmp %v", n.Type)
                }
        case OCLOSE:
                fn := syslook("closechan")
 
-               substArgTypes(&fn, n.Left.Type)
+               fn = substArgTypes(fn, n.Left.Type)
                n = mkcall1(fn, nil, init, n.Left)
 
        case OMAKECHAN:
                        var_ := temp(hmap(t))
 
                        a = Nod(OAS, var_, nil) // zero temp
-                       typecheck(&a, Etop)
+                       a = typecheck(a, Etop)
                        init.Append(a)
                        a = Nod(OADDR, var_, nil)
 
                        var_ = temp(mapbucket(t))
 
                        r = Nod(OAS, var_, nil) // zero temp
-                       typecheck(&r, Etop)
+                       r = typecheck(r, Etop)
                        init.Append(r)
                        r = Nod(OADDR, var_, nil)
                }
 
                fn := syslook("makemap")
-               substArgTypes(&fn, hmap(t), mapbucket(t), t.Key(), t.Type)
+               fn = substArgTypes(fn, hmap(t), mapbucket(t), t.Key(), t.Type)
                n = mkcall1(fn, n.Type, init, typename(n.Type), conv(n.Left, Types[TINT64]), a, r)
 
        case OMAKESLICE:
                        t = aindex(r, t.Type) // [r]T
                        var_ := temp(t)
                        a := Nod(OAS, var_, nil) // zero temp
-                       typecheck(&a, Etop)
+                       a = typecheck(a, Etop)
                        init.Append(a)
                        r := Nod(OSLICE, var_, Nod(OKEY, nil, l)) // arr[:l]
                        r = conv(r, n.Type)                       // in case n.Type is named.
-                       typecheck(&r, Erv)
-                       walkexpr(&r, init)
+                       r = typecheck(r, Erv)
+                       r = walkexpr(r, init)
                        n = r
                } else {
                        // makeslice(t *Type, nel int64, max int64) (ary []any)
                        fn := syslook("makeslice")
 
-                       substArgTypes(&fn, t.Type) // any-1
+                       fn = substArgTypes(fn, t.Type) // any-1
                        n = mkcall1(fn, n.Type, init, typename(n.Type), conv(l, Types[TINT64]), conv(r, Types[TINT64]))
                }
 
 
                n.Right = cheapexpr(n.Right, init)
                n.Left = cheapexpr(n.Left, init)
-               substArgTypes(&fn, n.Right.Type, n.Left.Type)
+               fn = substArgTypes(fn, n.Right.Type, n.Left.Type)
                r := mkcall1(fn, n.Type, init, n.Left, n.Right)
                // TODO(marvin): Fix Node.EType type union.
                if Op(n.Etype) == ONE {
                } else {
                        r = Nod(OOROR, Nod(ONE, Nod(OITAB, n.Left, nil), Nod(OITAB, n.Right, nil)), r)
                }
-               typecheck(&r, Erv)
-               walkexpr(&r, init)
+               r = typecheck(r, Erv)
+               r = walkexpr(r, init)
                r.Type = n.Type
                n = r
 
        case OSEND:
                n1 := n.Right
                n1 = assignconv(n1, n.Left.Type.Type, "chan send")
-               walkexpr(&n1, init)
+               n1 = walkexpr(n1, init)
                n1 = Nod(OADDR, n1, nil)
                n = mkcall1(chanfn("chansend1", 2, n.Left.Type), nil, init, typename(n.Left.Type), n.Left, n1)
 
        evconst(n)
        n.Type = t
        if n.Op == OLITERAL {
-               typecheck(&n, Erv)
+               n = typecheck(n, Erv)
        }
 
        ullmancalc(n)
        }
 
        lineno = lno
-       *np = n
+       return n
 }
 
 func reduceSlice(n *Node) *Node {
                // have been pulled from the output arguments
                if fncall(l, r.Type) {
                        tmp := temp(r.Type)
-                       typecheck(&tmp, Erv)
+                       tmp = typecheck(tmp, Erv)
                        a := Nod(OAS, l, tmp)
                        a = convas(a, init)
                        mm = append(mm, a)
                }
                n.List.Set(lr0)
                n.Esc = esc
-               typecheck(&n, Erv)
+               n = typecheck(n, Erv)
                if n.Type == nil {
                        Fatalf("mkdotargslice: typecheck failed")
                }
-               walkexpr(&n, init)
+               n = walkexpr(n, init)
        }
 
        a := Nod(OAS, nodarg(l, fp), n)
                a := Nod(OAS2, nil, nil)
                a.List.Set(alist)
                a.Rlist.Set(lr)
-               typecheck(&a, Etop)
-               walkstmt(&a)
+               a = typecheck(a, Etop)
+               a = walkstmt(a)
                init.Append(a)
                lr = alist
                r = lr[0]
                if n.Op == OLITERAL {
                        switch n.Val().Ctype() {
                        case CTRUNE:
-                               defaultlit(&n, runetype)
+                               n = defaultlit(n, runetype)
 
                        case CTINT:
-                               defaultlit(&n, Types[TINT64])
+                               n = defaultlit(n, Types[TINT64])
 
                        case CTFLT:
-                               defaultlit(&n, Types[TFLOAT64])
+                               n = defaultlit(n, Types[TFLOAT64])
                        }
                }
 
                if n.Op != OLITERAL && n.Type != nil && n.Type.Etype == TIDEAL {
-                       defaultlit(&n, Types[TINT64])
+                       n = defaultlit(n, Types[TINT64])
                }
-               defaultlit(&n, nil)
+               n = defaultlit(n, nil)
                all.SetIndex(i1, n)
                if n.Type == nil || n.Type.Etype == TFORW {
                        continue
                        } else {
                                on = syslook("printiface")
                        }
-                       substArgTypes(&on, n.Type) // any-1
+                       on = substArgTypes(on, n.Type) // any-1
                } else if Isptr[et] || et == TCHAN || et == TMAP || et == TFUNC || et == TUNSAFEPTR {
                        on = syslook("printpointer")
-                       substArgTypes(&on, n.Type) // any-1
+                       on = substArgTypes(on, n.Type) // any-1
                } else if Isslice(n.Type) {
                        on = syslook("printslice")
-                       substArgTypes(&on, n.Type) // any-1
+                       on = substArgTypes(on, n.Type) // any-1
                } else if Isint[et] {
                        if et == TUINT64 {
                                if (t.Sym.Pkg == Runtimepkg || compiling_runtime != 0) && t.Sym.Name == "hex" {
        walkexprlist(calls, init)
 
        r = Nod(OEMPTY, nil, nil)
-       typecheck(&r, Etop)
-       walkexpr(&r, init)
+       r = typecheck(r, Etop)
+       r = walkexpr(r, init)
        r.Ninit.Set(calls)
        return r
 }
 func callnew(t *Type) *Node {
        dowidth(t)
        fn := syslook("newobject")
-       substArgTypes(&fn, t)
+       fn = substArgTypes(fn, t)
        return mkcall1(fn, Ptrto(t), nil, typename(t))
 }
 
        }
 
        if isblank(n.Left) {
-               defaultlit(&n.Right, nil)
+               n.Right = defaultlit(n.Right, nil)
                goto out
        }
 
                map_ := n.Left.Left
                key := n.Left.Right
                val := n.Right
-               walkexpr(&map_, init)
-               walkexpr(&key, init)
-               walkexpr(&val, init)
+               map_ = walkexpr(map_, init)
+               key = walkexpr(key, init)
+               val = walkexpr(val, init)
 
                // orderexpr made sure key and val are addressable.
                key = Nod(OADDR, key, nil)
 
        if !Eqtype(lt, rt) {
                n.Right = assignconv(n.Right, lt, "assignment")
-               walkexpr(&n.Right, init)
+               n.Right = walkexpr(n.Right, init)
        }
 
 out:
                        }
 
                        if l.Op == OINDEX && Isfixedarray(l.Left.Type) {
-                               reorder3save(&l.Right, all, i, &early)
+                               l.Right = reorder3save(l.Right, all, i, &early)
                                l = l.Left
                                continue
                        }
                        break
 
                case OINDEX, OINDEXMAP:
-                       reorder3save(&l.Left, all, i, &early)
-                       reorder3save(&l.Right, all, i, &early)
+                       l.Left = reorder3save(l.Left, all, i, &early)
+                       l.Right = reorder3save(l.Right, all, i, &early)
                        if l.Op == OINDEXMAP {
                                all[i] = convas(all[i], &mapinit)
                        }
 
                case OIND, ODOTPTR:
-                       reorder3save(&l.Left, all, i, &early)
+                       l.Left = reorder3save(l.Left, all, i, &early)
                }
 
                // Save expression on right side.
-               reorder3save(&all[i].Right, all, i, &early)
+               all[i].Right = reorder3save(all[i].Right, all, i, &early)
        }
 
        early = append(mapinit.Slice(), early...)
 // assignments in all up to but not including the ith assignment,
 // copy into a temporary during *early and
 // replace *np with that temp.
-func reorder3save(np **Node, all []*Node, i int, early *[]*Node) {
-       n := *np
+// The result of reorder3save MUST be assigned back to n, e.g.
+//     n.Left = reorder3save(n.Left, all, i, early)
+func reorder3save(n *Node, all []*Node, i int, early *[]*Node) *Node {
        if !aliased(n, all, i) {
-               return
+               return n
        }
 
        q := temp(n.Type)
        q = Nod(OAS, q, n)
-       typecheck(&q, Etop)
+       q = typecheck(q, Etop)
        *early = append(*early, q)
-       *np = q.Left
+       return q.Left
 }
 
 // what's the outer value that a write to n affects?
                if v.Class&^PHEAP != PPARAMOUT {
                        as := Nod(OAS, v, v.Name.Param.Stackparam)
                        v.Name.Param.Stackparam.Typecheck = 1
-                       typecheck(&as, Etop)
+                       as = typecheck(as, Etop)
                        as = applywritebarrier(as)
                        nn = append(nn, as)
                }
        r := Nod(OCALL, fn, nil)
        r.List.Set(va[:n])
        if fn.Type.Results().NumFields() > 0 {
-               typecheck(&r, Erv|Efnstruct)
+               r = typecheck(r, Erv|Efnstruct)
        } else {
-               typecheck(&r, Etop)
+               r = typecheck(r, Etop)
        }
-       walkexpr(&r, init)
+       r = walkexpr(r, init)
        r.Type = t
        return r
 }
        }
        n = Nod(OCONV, n, nil)
        n.Type = t
-       typecheck(&n, Erv)
+       n = typecheck(n, Erv)
        return n
 }
 
        default:
                Fatalf("chanfn %d", n)
        case 1:
-               substArgTypes(&fn, t.Type)
+               fn = substArgTypes(fn, t.Type)
        case 2:
-               substArgTypes(&fn, t.Type, t.Type)
+               fn = substArgTypes(fn, t.Type, t.Type)
        }
        return fn
 }
                Fatalf("mapfn %v", t)
        }
        fn := syslook(name)
-       substArgTypes(&fn, t.Key(), t.Type, t.Key(), t.Type)
+       fn = substArgTypes(fn, t.Key(), t.Type, t.Key(), t.Type)
        return fn
 }
 
                Fatalf("mapfn %v", t)
        }
        fn := syslook(name)
-       substArgTypes(&fn, t.Key(), t.Type, t.Key())
+       fn = substArgTypes(fn, t.Key(), t.Type, t.Key())
        return fn
 }
 
 func writebarrierfn(name string, l *Type, r *Type) *Node {
        fn := syslook(name)
-       substArgTypes(&fn, l, r)
+       fn = substArgTypes(fn, l, r)
        return fn
 }
 
        cat := syslook(fn)
        r := Nod(OCALL, cat, nil)
        r.List.Set(args)
-       typecheck(&r, Erv)
-       walkexpr(&r, init)
+       r = typecheck(r, Erv)
+       r = walkexpr(r, init)
        r.Type = n.Type
 
        return r
 
        // instantiate growslice(Type*, []any, int) []any
        fn := syslook("growslice")
-       substArgTypes(&fn, s.Type.Type, s.Type.Type)
+       fn = substArgTypes(fn, s.Type.Type, s.Type.Type)
 
        // s = growslice(T, s, n)
        nif.Nbody.Set1(Nod(OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(s.Type), s, nn)))
                nptr1.Etype = 1
                nptr2 := l2
                fn := syslook("typedslicecopy")
-               substArgTypes(&fn, l1.Type, l2.Type)
+               fn = substArgTypes(fn, l1.Type, l2.Type)
                var ln Nodes
                ln.Set(l)
                nt := mkcall1(fn, Types[TINT], &ln, typename(l1.Type.Type), nptr1, nptr2)
                } else {
                        fn = syslook("slicecopy")
                }
-               substArgTypes(&fn, l1.Type, l2.Type)
+               fn = substArgTypes(fn, l1.Type, l2.Type)
                var ln Nodes
                ln.Set(l)
                nt := mkcall1(fn, Types[TINT], &ln, nptr1, nptr2, Nodintconst(s.Type.Type.Width))
                nptr2 := Nod(OSPTR, l2, nil)
 
                fn := syslook("memmove")
-               substArgTypes(&fn, s.Type.Type, s.Type.Type)
+               fn = substArgTypes(fn, s.Type.Type, s.Type.Type)
 
                var ln Nodes
                ln.Set(l)
 func walkappend(n *Node, init *Nodes, dst *Node) *Node {
        if !samesafeexpr(dst, n.List.First()) {
                n.List.SetIndex(0, safeexpr(n.List.Index(0), init))
-               walkexpr(n.List.Addr(0), init)
+               n.List.SetIndex(0, walkexpr(n.List.Index(0), init))
        }
        walkexprlistsafe(n.List.Slice()[1:], init)
 
        nx.Left = Nod(OLT, Nod(OSUB, Nod(OCAP, ns, nil), Nod(OLEN, ns, nil)), na)
 
        fn := syslook("growslice") //   growslice(<type>, old []T, mincap int) (ret []T)
-       substArgTypes(&fn, ns.Type.Type, ns.Type.Type)
+       fn = substArgTypes(fn, ns.Type.Type, ns.Type.Type)
 
        nx.Nbody.Set1(Nod(OAS, ns,
                mkcall1(fn, ns.Type, &nx.Ninit, typename(ns.Type), ns,
                } else {
                        fn = syslook("slicecopy")
                }
-               substArgTypes(&fn, n.Left.Type, n.Right.Type)
+               fn = substArgTypes(fn, n.Left.Type, n.Right.Type)
                return mkcall1(fn, n.Type, init, n.Left, n.Right, Nodintconst(n.Left.Type.Type.Width))
        }
 
-       walkexpr(&n.Left, init)
-       walkexpr(&n.Right, init)
+       n.Left = walkexpr(n.Left, init)
+       n.Right = walkexpr(n.Right, init)
        nl := temp(n.Left.Type)
        nr := temp(n.Right.Type)
        var l []*Node
        // Call memmove.
        fn := syslook("memmove")
 
-       substArgTypes(&fn, nl.Type.Type, nl.Type.Type)
+       fn = substArgTypes(fn, nl.Type.Type, nl.Type.Type)
        nwid := temp(Types[TUINTPTR])
        l = append(l, Nod(OAS, nwid, conv(nlen, Types[TUINTPTR])))
        nwid = Nod(OMUL, nwid, Nodintconst(nl.Type.Type.Width))
 
        if a == AMEM {
                n := syslook("memequal")
-               substArgTypes(&n, t, t)
+               n = substArgTypes(n, t, t)
                *needsize = 1
                return n
        }
        ntype.List.Append(Nod(ODCLFIELD, nil, typenod(Ptrto(t))))
        ntype.List.Append(Nod(ODCLFIELD, nil, typenod(Ptrto(t))))
        ntype.Rlist.Append(Nod(ODCLFIELD, nil, typenod(Types[TBOOL])))
-       typecheck(&ntype, Etype)
+       ntype = typecheck(ntype, Etype)
        n.Type = ntype.Type
        *needsize = 0
        return n
 }
 
-func walkcompare(np **Node, init *Nodes) {
-       n := *np
-
+// The result of walkcompare MUST be assigned back to n, e.g.
+//     n.Left = walkcompare(n.Left, init)
+func walkcompare(n *Node, init *Nodes) *Node {
        // Given interface value l and concrete value r, rewrite
        //   l == r
        // to
                x := temp(r.Type)
                if haspointers(r.Type) {
                        a := Nod(OAS, x, nil)
-                       typecheck(&a, Etop)
+                       a = typecheck(a, Etop)
                        init.Append(a)
                }
                ok := temp(Types[TBOOL])
                expr.List.Append(x)
                expr.List.Append(ok)
                expr.Rlist.Append(a)
-               typecheck(&expr, Etop)
-               walkexpr(&expr, init)
+               expr = typecheck(expr, Etop)
+               expr = walkexpr(expr, init)
 
                if n.Op == OEQ {
                        r = Nod(OANDAND, ok, Nod(OEQ, x, r))
                        r = Nod(OOROR, Nod(ONOT, ok, nil), Nod(ONE, x, r))
                }
                init.Append(expr)
-               finishcompare(np, n, r, init)
-               return
+               n = finishcompare(n, n, r, init)
+               return n
        }
 
        // Must be comparison of array or struct.
 
        switch t.Etype {
        default:
-               return
+               return n
 
        case TARRAY:
                if Isslice(t) {
-                       return
+                       return n
                }
 
        case TSTRUCT:
        l = temp(Ptrto(t))
        a := Nod(OAS, l, Nod(OADDR, cmpl, nil))
        a.Right.Etype = 1 // addr does not escape
-       typecheck(&a, Etop)
+       a = typecheck(a, Etop)
        init.Append(a)
 
        r = temp(Ptrto(t))
        a = Nod(OAS, r, Nod(OADDR, cmpr, nil))
        a.Right.Etype = 1 // addr does not escape
-       typecheck(&a, Etop)
+       a = typecheck(a, Etop)
        init.Append(a)
 
        var andor Op = OANDAND
                if expr == nil {
                        expr = Nodbool(n.Op == OEQ)
                }
-               finishcompare(np, n, expr, init)
-               return
+               n = finishcompare(n, n, expr, init)
+               return n
        }
 
        if t.Etype == TARRAY {
                // Zero- or single-element array, of any type.
                switch t.Bound {
                case 0:
-                       finishcompare(np, n, Nodbool(n.Op == OEQ), init)
-                       return
+                       n = finishcompare(n, n, Nodbool(n.Op == OEQ), init)
+                       return n
                case 1:
                        l0 := Nod(OINDEX, l, Nodintconst(0))
                        r0 := Nod(OINDEX, r, Nodintconst(0))
                        a := Nod(n.Op, l0, r0)
-                       finishcompare(np, n, a, init)
-                       return
+                       n = finishcompare(n, n, a, init)
+                       return n
                }
        }
 
                if expr == nil {
                        expr = Nodbool(n.Op == OEQ)
                }
-               finishcompare(np, n, expr, init)
-               return
+               n = finishcompare(n, n, expr, init)
+               return n
        }
 
        // Chose not to inline. Call equality function directly.
                r = Nod(ONOT, r, nil)
        }
 
-       finishcompare(np, n, r, init)
-       return
+       n = finishcompare(n, n, r, init)
+       return n
 }
 
-func finishcompare(np **Node, n, r *Node, init *Nodes) {
-       // Using np here to avoid passing &r to typecheck.
-       *np = r
-       typecheck(np, Erv)
-       walkexpr(np, init)
-       r = *np
+// The result of finishcompare MUST be assigned back to nn, e.g.
+//     n.Left = finishcompare(n.Left, x, r, init)
+func finishcompare(nn *Node, n, r *Node, init *Nodes) *Node {
+       // Use nn here to avoid passing r to typecheck.
+       nn = r
+       nn = typecheck(nn, Erv)
+       nn = walkexpr(nn, init)
+       r = nn
        if r.Type != n.Type {
                r = Nod(OCONVNOP, r, nil)
                r.Type = n.Type
                r.Typecheck = 1
-               *np = r
+               nn = r
        }
+       return nn
 }
 
 func samecheap(a *Node, b *Node) bool {
        return false
 }
 
-func walkrotate(np **Node) {
+// The result of walkrotate MUST be assigned back to n, e.g.
+//     n.Left = walkrotate(n.Left)
+func walkrotate(n *Node) *Node {
        if Thearch.Thechar == '0' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
-               return
+               return n
        }
 
-       n := *np
-
        // Want << | >> or >> | << or << ^ >> or >> ^ << on unsigned value.
        l := n.Left
 
        r := n.Right
        if (n.Op != OOR && n.Op != OXOR) || (l.Op != OLSH && l.Op != ORSH) || (r.Op != OLSH && r.Op != ORSH) || n.Type == nil || Issigned[n.Type.Etype] || l.Op == r.Op {
-               return
+               return n
        }
 
        // Want same, side effect-free expression on lhs of both shifts.
        if !samecheap(l.Left, r.Left) {
-               return
+               return n
        }
 
        // Constants adding to width?
                                if s == 0 || s == w {
                                        n = n.Left
                                }
-
-                               *np = n
-                               return
+                               return n
                        }
                }
-               return
+               return n
        }
 
        // TODO: Could allow s and 32-s if s is bounded (maybe s&31 and 32-s&31).
-       return
+       return n
 }
 
 // walkmul rewrites integer multiplication by powers of two as shifts.
-func walkmul(np **Node, init *Nodes) {
-       n := *np
+// The result of walkmul MUST be assigned back to n, e.g.
+//     n.Left = walkmul(n.Left, init)
+func walkmul(n *Node, init *Nodes) *Node {
        if !Isint[n.Type.Etype] {
-               return
+               return n
        }
 
        var nr *Node
                nl = n.Right
                nr = n.Left
        } else {
-               return
+               return n
        }
 
        neg := 0
        pow = powtwo(nr)
 
        if pow < 0 {
-               return
+               return n
        }
        if pow >= 1000 {
                // negative power of 2, like -16
 
        w = int(nl.Type.Width * 8)
        if pow+1 >= w { // too big, shouldn't happen
-               return
+               return n
        }
 
        nl = cheapexpr(nl, init)
                n = Nod(OMINUS, n, nil)
        }
 
-       typecheck(&n, Erv)
-       walkexpr(&n, init)
-       *np = n
+       n = typecheck(n, Erv)
+       n = walkexpr(n, init)
+       return n
 }
 
 // walkdiv rewrites division by a constant as less expensive
 // operations.
-func walkdiv(np **Node, init *Nodes) {
+// The result of walkdiv MUST be assigned back to n, e.g.
+//     n.Left = walkdiv(n.Left, init)
+func walkdiv(n *Node, init *Nodes) *Node {
        // if >= 0, nr is 1<<pow // 1 if nr is negative.
 
        // TODO(minux)
        if Thearch.Thechar == '0' || Thearch.Thechar == '7' || Thearch.Thechar == '9' {
-               return
+               return n
        }
 
-       n := *np
        if n.Right.Op != OLITERAL {
-               return
+               return n
        }
 
        // nr is a constant.
 
        if pow+1 >= w {
                // divisor too large.
-               return
+               return n
        }
 
        if pow < 0 {
                }
 
                if m.Bad != 0 {
-                       return
+                       return n
                }
 
                // We have a quick division method so use it
 
                switch Simtype[nl.Type.Etype] {
                default:
-                       return
+                       return n
 
                        // n1 = nl * magic >> w (HMUL)
                case TUINT8, TUINT16, TUINT32:
 
                        Nodconst(nc, nl.Type, int64(m.Um))
                        n1 := Nod(OHMUL, nl, nc)
-                       typecheck(&n1, Erv)
+                       n1 = typecheck(n1, Erv)
                        if m.Ua != 0 {
                                // Select a Go type with (at least) twice the width.
                                var twide *Type
                                switch Simtype[nl.Type.Etype] {
                                default:
-                                       return
+                                       return n
 
                                case TUINT8, TUINT16:
                                        twide = Types[TUINT32]
 
                        Nodconst(nc, nl.Type, m.Sm)
                        n1 := Nod(OHMUL, nl, nc)
-                       typecheck(&n1, Erv)
+                       n1 = typecheck(n1, Erv)
                        if m.Sm < 0 {
                                // add the numerator.
                                n1 = Nod(OADD, n1, nl)
                                Nodconst(nc, Types[Simtype[TUINT]], int64(w)-1)
                                n1 := Nod(ORSH, nl, nc) // n1 = -1 iff nl < 0.
                                if pow == 1 {
-                                       typecheck(&n1, Erv)
+                                       n1 = typecheck(n1, Erv)
                                        n1 = cheapexpr(n1, init)
 
                                        // n = (nl+ε)&1 -ε where ε=1 iff nl<0.
 
                                        Nodconst(nc, nl.Type, (1<<uint(pow))-1)
                                        n2 := Nod(OAND, n1, nc) // n2 = 2^pow-1 iff nl<0.
-                                       typecheck(&n2, Erv)
+                                       n2 = typecheck(n2, Erv)
                                        n2 = cheapexpr(n2, init)
 
                                        n3 := Nod(OADD, nl, n2)
        goto ret
 
 ret:
-       typecheck(&n, Erv)
-       walkexpr(&n, init)
-       *np = n
+       n = typecheck(n, Erv)
+       n = walkexpr(n, init)
+       return n
 }
 
 // return 1 if integer n must be in range [0, max), 0 otherwise
 
 var walkprintfunc_prgen int
 
-func walkprintfunc(np **Node, init *Nodes) {
-       n := *np
-
+// The result of walkprintfunc MUST be assigned back to n, e.g.
+//     n.Left = walkprintfunc(n.Left, init)
+func walkprintfunc(n *Node, init *Nodes) *Node {
        if n.Ninit.Len() != 0 {
                walkstmtlist(n.Ninit.Slice())
                init.AppendNodes(&n.Ninit)
 
        a = Nod(n.Op, nil, nil)
        a.List.Set(printargs)
-       typecheck(&a, Etop)
-       walkstmt(&a)
+       a = typecheck(a, Etop)
+       a = walkstmt(a)
 
        fn.Nbody.Set1(a)
 
        funcbody(fn)
 
-       typecheck(&fn, Etop)
+       fn = typecheck(fn, Etop)
        typecheckslice(fn.Nbody.Slice(), Etop)
        xtop = append(xtop, fn)
        Curfn = oldfn
        a = Nod(OCALL, nil, nil)
        a.Left = fn.Func.Nname
        a.List.Set(n.List.Slice())
-       typecheck(&a, Etop)
-       walkexpr(&a, init)
-       *np = a
+       a = typecheck(a, Etop)
+       a = walkexpr(a, init)
+       return a
 }