]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.regabi] cmd/compile: arrange for walkstmt, walkexpr, to return from switch cases
authorRuss Cox <rsc@golang.org>
Mon, 7 Dec 2020 05:04:54 +0000 (00:04 -0500)
committerRuss Cox <rsc@golang.org>
Wed, 9 Dec 2020 17:05:19 +0000 (17:05 +0000)
Ending them in a returning switch makes it safe for each case
to do an appropriate type assertion.

Passes buildall w/ toolstash -cmp.

Change-Id: I55d8f0a555006104164d84d27822aa8c5ad68515
Reviewed-on: https://go-review.googlesource.com/c/go/+/275882
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/gc/walk.go

index 4189d1a721735cd20acd702af6fb4074fc8ec407..f35e9d768bd491527ce60612ada9573c1b56fae6 100644 (file)
@@ -123,6 +123,7 @@ func walkstmt(n ir.Node) ir.Node {
                        base.Errorf("%v is not a top level statement", n.Op())
                }
                ir.Dump("nottop", n)
+               return n
 
        case ir.OAS,
                ir.OASOP,
@@ -166,6 +167,7 @@ func walkstmt(n ir.Node) ir.Node {
                                n = ir.NewBlockStmt(n.Pos(), init.Slice())
                        }
                }
+               return n
 
        // special case for a receive where we throw away
        // the value received.
@@ -179,8 +181,7 @@ func walkstmt(n ir.Node) ir.Node {
                n.SetLeft(walkexpr(n.Left(), &init))
                n = mkcall1(chanfn("chanrecv1", 2, n.Left().Type()), nil, &init, n.Left(), nodnil())
                n = walkexpr(n, &init)
-
-               n = initExpr(init.Slice(), n)
+               return initExpr(init.Slice(), n)
 
        case ir.OBREAK,
                ir.OCONTINUE,
@@ -193,7 +194,7 @@ func walkstmt(n ir.Node) ir.Node {
                ir.OVARDEF,
                ir.OVARKILL,
                ir.OVARLIVE:
-               break
+               return n
 
        case ir.ODCL:
                v := n.Left()
@@ -209,12 +210,15 @@ func walkstmt(n ir.Node) ir.Node {
                        nn = typecheck(nn, ctxStmt)
                        return walkstmt(nn)
                }
+               return n
 
        case ir.OBLOCK:
                walkstmtlist(n.List().Slice())
+               return n
 
        case ir.OCASE:
                base.Errorf("case statement out of place")
+               panic("unreachable")
 
        case ir.ODEFER:
                Curfn.SetHasDefer(true)
@@ -261,6 +265,7 @@ func walkstmt(n ir.Node) ir.Node {
                        init.Append(n)
                        n = ir.NewBlockStmt(n.Pos(), init.Slice())
                }
+               return n
 
        case ir.OFOR, ir.OFORUNTIL:
                if n.Left() != nil {
@@ -276,16 +281,18 @@ func walkstmt(n ir.Node) ir.Node {
                        walkstmtlist(n.List().Slice())
                }
                walkstmtlist(n.Body().Slice())
+               return n
 
        case ir.OIF:
                n.SetLeft(walkexpr(n.Left(), n.PtrInit()))
                walkstmtlist(n.Body().Slice())
                walkstmtlist(n.Rlist().Slice())
+               return n
 
        case ir.ORETURN:
                Curfn.NumReturns++
                if n.List().Len() == 0 {
-                       break
+                       return n
                }
                if (hasNamedResults(Curfn) && n.List().Len() > 1) || paramoutheap(Curfn) {
                        // assign to the function out parameters,
@@ -317,7 +324,7 @@ func walkstmt(n ir.Node) ir.Node {
 
                        ll := ascompatee(n.Op(), rl, n.List().Slice(), n.PtrInit())
                        n.PtrList().Set(reorder3(ll))
-                       break
+                       return n
                }
                walkexprlist(n.List().Slice(), n.PtrInit())
 
@@ -334,27 +341,29 @@ func walkstmt(n ir.Node) ir.Node {
                        res[i] = convas(a, n.PtrInit())
                }
                n.PtrList().Set(res)
+               return n
 
        case ir.ORETJMP:
-               break
+               return n
 
        case ir.OINLMARK:
-               break
+               return n
 
        case ir.OSELECT:
                walkselect(n)
+               return n
 
        case ir.OSWITCH:
                walkswitch(n)
+               return n
 
        case ir.ORANGE:
-               n = walkrange(n)
+               return walkrange(n)
        }
 
-       if n.Op() == ir.ONAME {
-               base.Fatalf("walkstmt ended up with name: %+v", n)
-       }
-       return n
+       // No return! Each case must return (or panic),
+       // to avoid confusion about what gets returned
+       // in the presence of type assertions.
 }
 
 // walk the whole tree of the body of an
@@ -477,31 +486,68 @@ func walkexpr(n ir.Node, init *ir.Nodes) ir.Node {
                return nn
        }
 
-opswitch:
+       n = walkexpr1(n, init)
+
+       // Expressions that are constant at run time but not
+       // considered const by the language spec are not turned into
+       // constants until walk. For example, if n is y%1 == 0, the
+       // walk of y%1 may have replaced it by 0.
+       // Check whether n with its updated args is itself now a constant.
+       t := n.Type()
+       n = evalConst(n)
+       if n.Type() != t {
+               base.Fatalf("evconst changed Type: %v had type %v, now %v", n, t, n.Type())
+       }
+       if n.Op() == ir.OLITERAL {
+               n = typecheck(n, ctxExpr)
+               // Emit string symbol now to avoid emitting
+               // any concurrently during the backend.
+               if v := n.Val(); v.Kind() == constant.String {
+                       _ = stringsym(n.Pos(), constant.StringVal(v))
+               }
+       }
+
+       updateHasCall(n)
+
+       if base.Flag.LowerW != 0 && n != nil {
+               ir.Dump("after walk expr", n)
+       }
+
+       base.Pos = lno
+       return n
+}
+
+func walkexpr1(n ir.Node, init *ir.Nodes) ir.Node {
        switch n.Op() {
        default:
                ir.Dump("walk", n)
                base.Fatalf("walkexpr: switch 1 unknown op %+v", n.Op())
+               panic("unreachable")
 
        case ir.ONONAME, ir.OGETG, ir.ONEWOBJ, ir.OMETHEXPR:
+               return n
 
        case ir.OTYPE, ir.ONAME, ir.OLITERAL, ir.ONIL:
                // TODO(mdempsky): Just return n; see discussion on CL 38655.
                // Perhaps refactor to use Node.mayBeShared for these instead.
                // If these return early, make sure to still call
                // stringsym for constant strings.
+               return n
 
        case ir.ONOT, ir.ONEG, ir.OPLUS, ir.OBITNOT, ir.OREAL, ir.OIMAG, ir.ODOTMETH, ir.ODOTINTER,
                ir.ODEREF, ir.OSPTR, ir.OITAB, ir.OIDATA, ir.OADDR:
                n.SetLeft(walkexpr(n.Left(), init))
+               return n
 
        case ir.OEFACE, ir.OAND, ir.OANDNOT, ir.OSUB, ir.OMUL, ir.OADD, ir.OOR, ir.OXOR, ir.OLSH, ir.ORSH:
                n.SetLeft(walkexpr(n.Left(), init))
                n.SetRight(walkexpr(n.Right(), init))
+               return n
 
        case ir.ODOT, ir.ODOTPTR:
                usefield(n)
                n.SetLeft(walkexpr(n.Left(), init))
+               return n
 
        case ir.ODOTTYPE, ir.ODOTTYPE2:
                n.SetLeft(walkexpr(n.Left(), init))
@@ -513,12 +559,12 @@ opswitch:
                if !n.Type().IsInterface() && !n.Left().Type().IsEmptyInterface() {
                        n.PtrList().Set1(itabname(n.Type(), n.Left().Type()))
                }
+               return n
 
        case ir.OLEN, ir.OCAP:
                if isRuneCount(n) {
                        // Replace len([]rune(string)) with runtime.countrunes(string).
-                       n = mkcall("countrunes", n.Type(), init, conv(n.Left().Left(), types.Types[types.TSTRING]))
-                       break
+                       return mkcall("countrunes", n.Type(), init, conv(n.Left().Left(), types.Types[types.TSTRING]))
                }
 
                n.SetLeft(walkexpr(n.Left(), init))
@@ -535,6 +581,7 @@ opswitch:
                        n = origIntConst(n, t.NumElem())
                        n.SetTypecheck(1)
                }
+               return n
 
        case ir.OCOMPLEX:
                // Use results from call expression as arguments for complex.
@@ -544,9 +591,10 @@ opswitch:
                }
                n.SetLeft(walkexpr(n.Left(), init))
                n.SetRight(walkexpr(n.Right(), init))
+               return n
 
        case ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE:
-               n = walkcompare(n, init)
+               return walkcompare(n, init)
 
        case ir.OANDAND, ir.OOROR:
                n.SetLeft(walkexpr(n.Left(), init))
@@ -558,17 +606,19 @@ opswitch:
 
                n.SetRight(walkexpr(n.Right(), &ll))
                n.SetRight(initExpr(ll.Slice(), n.Right()))
+               return n
 
        case ir.OPRINT, ir.OPRINTN:
-               n = walkprint(n, init)
+               return walkprint(n, init)
 
        case ir.OPANIC:
-               n = mkcall("gopanic", nil, init, n.Left())
+               return mkcall("gopanic", nil, init, n.Left())
 
        case ir.ORECOVER:
-               n = mkcall("gorecover", n.Type(), init, ir.Nod(ir.OADDR, nodfp, nil))
+               return mkcall("gorecover", n.Type(), init, ir.Nod(ir.OADDR, nodfp, nil))
 
        case ir.OCLOSUREREAD, ir.OCFUNC:
+               return n
 
        case ir.OCALLINTER, ir.OCALLFUNC, ir.OCALLMETH:
                if n.Op() == ir.OCALLINTER {
@@ -597,6 +647,7 @@ opswitch:
                }
 
                walkCall(n, init)
+               return n
 
        case ir.OAS, ir.OASOP:
                init.AppendNodes(n.PtrInit())
@@ -622,17 +673,16 @@ opswitch:
                }
 
                if oaslit(n, init) {
-                       n = ir.NodAt(n.Pos(), ir.OBLOCK, nil, nil)
-                       break
+                       return ir.NodAt(n.Pos(), ir.OBLOCK, nil, nil)
                }
 
                if n.Right() == nil {
                        // TODO(austin): Check all "implicit zeroing"
-                       break
+                       return n
                }
 
                if !instrumenting && isZero(n.Right()) {
-                       break
+                       return n
                }
 
                switch n.Right().Op() {
@@ -646,9 +696,7 @@ opswitch:
 
                        n1 := ir.Nod(ir.OADDR, n.Left(), nil)
                        r := n.Right().Left() // the channel
-                       n = mkcall1(chanfn("chanrecv1", 2, r.Type()), nil, init, r, n1)
-                       n = walkexpr(n, init)
-                       break opswitch
+                       return mkcall1(chanfn("chanrecv1", 2, r.Type()), nil, init, r, n1)
 
                case ir.OAPPEND:
                        // x = append(...)
@@ -671,7 +719,7 @@ opswitch:
                                // Do not add a new write barrier.
                                // Set up address of type for back end.
                                r.SetLeft(typename(r.Type().Elem()))
-                               break opswitch
+                               return n
                        }
                        // Otherwise, lowered for race detector.
                        // Treat as ordinary assignment.
@@ -680,6 +728,7 @@ opswitch:
                if n.Left() != nil && n.Right() != nil {
                        n = convas(n, init)
                }
+               return n
 
        case ir.OAS2:
                init.AppendNodes(n.PtrInit())
@@ -687,7 +736,7 @@ opswitch:
                walkexprlistsafe(n.Rlist().Slice(), init)
                ll := ascompatee(ir.OAS, n.List().Slice(), n.Rlist().Slice(), init)
                ll = reorder3(ll)
-               n = liststmt(ll)
+               return liststmt(ll)
 
        // a,b,... = fn()
        case ir.OAS2FUNC:
@@ -699,12 +748,12 @@ opswitch:
 
                if isIntrinsicCall(r) {
                        n.PtrRlist().Set1(r)
-                       break
+                       return n
                }
                init.Append(r)
 
                ll := ascompatet(n.List(), r.Type())
-               n = liststmt(ll)
+               return liststmt(ll)
 
        // x, y = <-c
        // order.stmt made sure x is addressable or blank.
@@ -724,7 +773,7 @@ opswitch:
                ok := n.List().Second()
                call := mkcall1(fn, types.Types[types.TBOOL], init, r.Left(), n1)
                n = ir.Nod(ir.OAS, ok, call)
-               n = typecheck(n, ctxStmt)
+               return typecheck(n, ctxStmt)
 
        // a,b = m[i]
        case ir.OAS2MAPR:
@@ -784,7 +833,7 @@ opswitch:
                }
 
                n = typecheck(n, ctxStmt)
-               n = walkexpr(n, init)
+               return walkexpr(n, init)
 
        case ir.ODELETE:
                init.AppendNodes(n.PtrInit())
@@ -799,11 +848,12 @@ opswitch:
                        // order.stmt made sure key is addressable.
                        key = ir.Nod(ir.OADDR, key, nil)
                }
-               n = mkcall1(mapfndel(mapdelete[fast], t), nil, init, typename(t), map_, key)
+               return mkcall1(mapfndel(mapdelete[fast], t), nil, init, typename(t), map_, key)
 
        case ir.OAS2DOTTYPE:
                walkexprlistsafe(n.List().Slice(), init)
                n.PtrRlist().SetIndex(0, walkexpr(n.Rlist().First(), init))
+               return n
 
        case ir.OCONVIFACE:
                n.SetLeft(walkexpr(n.Left(), init))
@@ -828,8 +878,7 @@ opswitch:
                        l := ir.Nod(ir.OEFACE, typeword(), n.Left())
                        l.SetType(toType)
                        l.SetTypecheck(n.Typecheck())
-                       n = l
-                       break
+                       return l
                }
 
                if staticuint64s == nil {
@@ -878,8 +927,7 @@ opswitch:
                        l := ir.Nod(ir.OEFACE, typeword(), typecheck(ir.Nod(ir.OADDR, value, nil), ctxExpr))
                        l.SetType(toType)
                        l.SetTypecheck(n.Typecheck())
-                       n = l
-                       break
+                       return l
                }
 
                // Implement interface to empty interface conversion.
@@ -906,8 +954,7 @@ opswitch:
                        e := ir.Nod(ir.OEFACE, tmp, ifaceData(n.Pos(), c, types.NewPtr(types.Types[types.TUINT8])))
                        e.SetType(toType) // assign type manually, typecheck doesn't understand OEFACE.
                        e.SetTypecheck(1)
-                       n = e
-                       break
+                       return e
                }
 
                fnname, needsaddr := convFuncName(fromType, toType)
@@ -928,8 +975,7 @@ opswitch:
                        e := ir.Nod(ir.OEFACE, typeword(), call)
                        e.SetType(toType)
                        e.SetTypecheck(1)
-                       n = e
-                       break
+                       return e
                }
 
                var tab ir.Node
@@ -962,7 +1008,7 @@ opswitch:
                n = ir.Nod(ir.OCALL, fn, nil)
                n.PtrList().Set2(tab, v)
                n = typecheck(n, ctxExpr)
-               n = walkexpr(n, init)
+               return walkexpr(n, init)
 
        case ir.OCONV, ir.OCONVNOP:
                n.SetLeft(walkexpr(n.Left(), init))
@@ -971,20 +1017,18 @@ opswitch:
                }
                if n.Op() == ir.OCONVNOP && checkPtr(Curfn, 1) {
                        if n.Type().IsPtr() && n.Left().Type().IsUnsafePtr() { // unsafe.Pointer to *T
-                               n = walkCheckPtrAlignment(n, init, nil)
-                               break
+                               return walkCheckPtrAlignment(n, init, nil)
                        }
                        if n.Type().IsUnsafePtr() && n.Left().Type().IsUintptr() { // uintptr to unsafe.Pointer
-                               n = walkCheckPtrArithmetic(n, init)
-                               break
+                               return walkCheckPtrArithmetic(n, init)
                        }
                }
                param, result := rtconvfn(n.Left().Type(), n.Type())
                if param == types.Txxx {
-                       break
+                       return n
                }
                fn := types.BasicTypeNames[param] + "to" + types.BasicTypeNames[result]
-               n = conv(mkcall(fn, types.Types[result], init, conv(n.Left(), types.Types[param])), n.Type())
+               return conv(mkcall(fn, types.Types[result], init, conv(n.Left(), types.Types[param])), n.Type())
 
        case ir.ODIV, ir.OMOD:
                n.SetLeft(walkexpr(n.Left(), init))
@@ -996,13 +1040,12 @@ opswitch:
                if isComplex[et] && n.Op() == ir.ODIV {
                        t := n.Type()
                        n = mkcall("complex128div", types.Types[types.TCOMPLEX128], init, conv(n.Left(), types.Types[types.TCOMPLEX128]), conv(n.Right(), types.Types[types.TCOMPLEX128]))
-                       n = conv(n, t)
-                       break
+                       return conv(n, t)
                }
 
                // Nothing to do for float divisions.
                if isFloat[et] {
-                       break
+                       return n
                }
 
                // rewrite 64-bit div and mod on 32-bit architectures.
@@ -1019,15 +1062,15 @@ opswitch:
                                                c = -c
                                        }
                                        if c != 0 && c&(c-1) == 0 {
-                                               break opswitch
+                                               return n
                                        }
                                case types.TUINT64:
                                        c := ir.Uint64Val(n.Right())
                                        if c < 1<<16 {
-                                               break opswitch
+                                               return n
                                        }
                                        if c != 0 && c&(c-1) == 0 {
-                                               break opswitch
+                                               return n
                                        }
                                }
                        }
@@ -1042,8 +1085,9 @@ opswitch:
                        } else {
                                fn += "mod"
                        }
-                       n = mkcall(fn, n.Type(), init, conv(n.Left(), types.Types[et]), conv(n.Right(), types.Types[et]))
+                       return mkcall(fn, n.Type(), init, conv(n.Left(), types.Types[et]), conv(n.Right(), types.Types[et]))
                }
+               return n
 
        case ir.OINDEX:
                n.SetLeft(walkexpr(n.Left(), init))
@@ -1057,7 +1101,7 @@ opswitch:
                // if range of type cannot exceed static array bound,
                // disable bounds check.
                if n.Bounded() {
-                       break
+                       return n
                }
                t := n.Left().Type()
                if t != nil && t.IsPtr() {
@@ -1086,6 +1130,7 @@ opswitch:
                                base.Errorf("index out of bounds")
                        }
                }
+               return n
 
        case ir.OINDEXMAP:
                // Replace m[k] with *map{access1,assign}(maptype, m, &k)
@@ -1124,14 +1169,17 @@ opswitch:
                n = ir.Nod(ir.ODEREF, n, nil)
                n.SetType(t.Elem())
                n.SetTypecheck(1)
+               return n
 
        case ir.ORECV:
                base.Fatalf("walkexpr ORECV") // should see inside OAS only
+               panic("unreachable")
 
        case ir.OSLICEHEADER:
                n.SetLeft(walkexpr(n.Left(), init))
                n.List().SetFirst(walkexpr(n.List().First(), init))
                n.List().SetSecond(walkexpr(n.List().Second(), init))
+               return n
 
        case ir.OSLICE, ir.OSLICEARR, ir.OSLICESTR, ir.OSLICE3, ir.OSLICE3ARR:
                checkSlice := checkPtr(Curfn, 1) && n.Op() == ir.OSLICE3ARR && n.Left().Op() == ir.OCONVNOP && n.Left().Left().Type().IsUnsafePtr()
@@ -1160,11 +1208,11 @@ opswitch:
                                } else {
                                        n.SetOp(ir.OSLICEARR)
                                }
-                               n = reduceSlice(n)
+                               return reduceSlice(n)
                        }
-               } else {
-                       n = reduceSlice(n)
+                       return n
                }
+               return reduceSlice(n)
 
        case ir.ONEW:
                if n.Type().Elem().NotInHeap() {
@@ -1179,28 +1227,26 @@ opswitch:
                        r = typecheck(r, ctxStmt)
                        init.Append(r)
                        r = ir.Nod(ir.OADDR, r.Left(), nil)
-                       r = typecheck(r, ctxExpr)
-                       n = r
-               } else {
-                       n = callnew(n.Type().Elem())
+                       return typecheck(r, ctxExpr)
                }
+               return callnew(n.Type().Elem())
 
        case ir.OADDSTR:
-               n = addstr(n, init)
+               return addstr(n, init)
 
        case ir.OAPPEND:
                // order should make sure we only see OAS(node, OAPPEND), which we handle above.
                base.Fatalf("append outside assignment")
+               panic("unreachable")
 
        case ir.OCOPY:
-               n = copyany(n, init, instrumenting && !base.Flag.CompilingRuntime)
+               return copyany(n, init, instrumenting && !base.Flag.CompilingRuntime)
 
-               // cannot use chanfn - closechan takes any, not chan any
        case ir.OCLOSE:
+               // cannot use chanfn - closechan takes any, not chan any
                fn := syslook("closechan")
-
                fn = substArgTypes(fn, n.Left().Type())
-               n = mkcall1(fn, nil, init, n.Left())
+               return mkcall1(fn, nil, init, n.Left())
 
        case ir.OMAKECHAN:
                // When size fits into int, use makechan instead of
@@ -1217,7 +1263,7 @@ opswitch:
                        argtype = types.Types[types.TINT]
                }
 
-               n = mkcall1(chanfn(fnname, 1, n.Type()), n.Type(), init, typename(n.Type()), conv(size, argtype))
+               return mkcall1(chanfn(fnname, 1, n.Type()), n.Type(), init, typename(n.Type()), conv(size, argtype))
 
        case ir.OMAKEMAP:
                t := n.Type()
@@ -1294,42 +1340,41 @@ opswitch:
                                a = typecheck(a, ctxStmt)
                                a = walkexpr(a, init)
                                init.Append(a)
-                               n = convnop(h, t)
-                       } else {
-                               // Call runtime.makehmap to allocate an
-                               // hmap on the heap and initialize hmap's hash0 field.
-                               fn := syslook("makemap_small")
-                               fn = substArgTypes(fn, t.Key(), t.Elem())
-                               n = mkcall1(fn, n.Type(), init)
-                       }
-               } else {
-                       if n.Esc() != EscNone {
-                               h = nodnil()
-                       }
-                       // Map initialization with a variable or large hint is
-                       // more complicated. We therefore generate a call to
-                       // runtime.makemap to initialize hmap and allocate the
-                       // map buckets.
-
-                       // When hint fits into int, use makemap instead of
-                       // makemap64, which is faster and shorter on 32 bit platforms.
-                       fnname := "makemap64"
-                       argtype := types.Types[types.TINT64]
-
-                       // Type checking guarantees that TIDEAL hint is positive and fits in an int.
-                       // See checkmake call in TMAP case of OMAKE case in OpSwitch in typecheck1 function.
-                       // The case of hint overflow when converting TUINT or TUINTPTR to TINT
-                       // will be handled by the negative range checks in makemap during runtime.
-                       if hint.Type().IsKind(types.TIDEAL) || hint.Type().Size() <= types.Types[types.TUINT].Size() {
-                               fnname = "makemap"
-                               argtype = types.Types[types.TINT]
+                               return convnop(h, t)
                        }
+                       // Call runtime.makehmap to allocate an
+                       // hmap on the heap and initialize hmap's hash0 field.
+                       fn := syslook("makemap_small")
+                       fn = substArgTypes(fn, t.Key(), t.Elem())
+                       return mkcall1(fn, n.Type(), init)
+               }
 
-                       fn := syslook(fnname)
-                       fn = substArgTypes(fn, hmapType, t.Key(), t.Elem())
-                       n = mkcall1(fn, n.Type(), init, typename(n.Type()), conv(hint, argtype), h)
+               if n.Esc() != EscNone {
+                       h = nodnil()
+               }
+               // Map initialization with a variable or large hint is
+               // more complicated. We therefore generate a call to
+               // runtime.makemap to initialize hmap and allocate the
+               // map buckets.
+
+               // When hint fits into int, use makemap instead of
+               // makemap64, which is faster and shorter on 32 bit platforms.
+               fnname := "makemap64"
+               argtype := types.Types[types.TINT64]
+
+               // Type checking guarantees that TIDEAL hint is positive and fits in an int.
+               // See checkmake call in TMAP case of OMAKE case in OpSwitch in typecheck1 function.
+               // The case of hint overflow when converting TUINT or TUINTPTR to TINT
+               // will be handled by the negative range checks in makemap during runtime.
+               if hint.Type().IsKind(types.TIDEAL) || hint.Type().Size() <= types.Types[types.TUINT].Size() {
+                       fnname = "makemap"
+                       argtype = types.Types[types.TINT]
                }
 
+               fn := syslook(fnname)
+               fn = substArgTypes(fn, hmapType, t.Key(), t.Elem())
+               return mkcall1(fn, n.Type(), init, typename(n.Type()), conv(hint, argtype), h)
+
        case ir.OMAKESLICE:
                l := n.Left()
                r := n.Right()
@@ -1376,39 +1421,39 @@ opswitch:
                        r = conv(r, n.Type()) // in case n.Type is named.
                        r = typecheck(r, ctxExpr)
                        r = walkexpr(r, init)
-                       n = r
-               } else {
-                       // n escapes; set up a call to makeslice.
-                       // When len and cap can fit into int, use makeslice instead of
-                       // makeslice64, which is faster and shorter on 32 bit platforms.
-
-                       len, cap := l, r
-
-                       fnname := "makeslice64"
-                       argtype := types.Types[types.TINT64]
-
-                       // Type checking guarantees that TIDEAL len/cap are positive and fit in an int.
-                       // The case of len or cap overflow when converting TUINT or TUINTPTR to TINT
-                       // will be handled by the negative range checks in makeslice during runtime.
-                       if (len.Type().IsKind(types.TIDEAL) || len.Type().Size() <= types.Types[types.TUINT].Size()) &&
-                               (cap.Type().IsKind(types.TIDEAL) || cap.Type().Size() <= types.Types[types.TUINT].Size()) {
-                               fnname = "makeslice"
-                               argtype = types.Types[types.TINT]
-                       }
+                       return r
+               }
 
-                       m := ir.Nod(ir.OSLICEHEADER, nil, nil)
-                       m.SetType(t)
+               // n escapes; set up a call to makeslice.
+               // When len and cap can fit into int, use makeslice instead of
+               // makeslice64, which is faster and shorter on 32 bit platforms.
 
-                       fn := syslook(fnname)
-                       m.SetLeft(mkcall1(fn, types.Types[types.TUNSAFEPTR], init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype)))
-                       m.Left().MarkNonNil()
-                       m.PtrList().Set2(conv(len, types.Types[types.TINT]), conv(cap, types.Types[types.TINT]))
+               len, cap := l, r
+
+               fnname := "makeslice64"
+               argtype := types.Types[types.TINT64]
 
-                       m = typecheck(m, ctxExpr)
-                       m = walkexpr(m, init)
-                       n = m
+               // Type checking guarantees that TIDEAL len/cap are positive and fit in an int.
+               // The case of len or cap overflow when converting TUINT or TUINTPTR to TINT
+               // will be handled by the negative range checks in makeslice during runtime.
+               if (len.Type().IsKind(types.TIDEAL) || len.Type().Size() <= types.Types[types.TUINT].Size()) &&
+                       (cap.Type().IsKind(types.TIDEAL) || cap.Type().Size() <= types.Types[types.TUINT].Size()) {
+                       fnname = "makeslice"
+                       argtype = types.Types[types.TINT]
                }
 
+               m := ir.Nod(ir.OSLICEHEADER, nil, nil)
+               m.SetType(t)
+
+               fn := syslook(fnname)
+               m.SetLeft(mkcall1(fn, types.Types[types.TUNSAFEPTR], init, typename(t.Elem()), conv(len, argtype), conv(cap, argtype)))
+               m.Left().MarkNonNil()
+               m.PtrList().Set2(conv(len, types.Types[types.TINT]), conv(cap, types.Types[types.TINT]))
+
+               m = typecheck(m, ctxExpr)
+               m = walkexpr(m, init)
+               return m
+
        case ir.OMAKESLICECOPY:
                if n.Esc() == EscNone {
                        base.Fatalf("OMAKESLICECOPY with EscNone: %v", n)
@@ -1453,18 +1498,18 @@ opswitch:
                        ncopy = walkexpr(ncopy, init)
                        init.Append(ncopy)
 
-                       n = s
-               } else { // Replace make+copy with runtime.makeslicecopy.
-                       // instantiate makeslicecopy(typ *byte, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer
-                       fn := syslook("makeslicecopy")
-                       s := ir.Nod(ir.OSLICEHEADER, nil, nil)
-                       s.SetLeft(mkcall1(fn, types.Types[types.TUNSAFEPTR], init, typename(t.Elem()), length, copylen, conv(copyptr, types.Types[types.TUNSAFEPTR])))
-                       s.Left().MarkNonNil()
-                       s.PtrList().Set2(length, length)
-                       s.SetType(t)
-                       n = typecheck(s, ctxExpr)
-                       n = walkexpr(n, init)
+                       return s
                }
+               // Replace make+copy with runtime.makeslicecopy.
+               // instantiate makeslicecopy(typ *byte, tolen int, fromlen int, from unsafe.Pointer) unsafe.Pointer
+               fn := syslook("makeslicecopy")
+               s := ir.Nod(ir.OSLICEHEADER, nil, nil)
+               s.SetLeft(mkcall1(fn, types.Types[types.TUNSAFEPTR], init, typename(t.Elem()), length, copylen, conv(copyptr, types.Types[types.TUNSAFEPTR])))
+               s.Left().MarkNonNil()
+               s.PtrList().Set2(length, length)
+               s.SetType(t)
+               n = typecheck(s, ctxExpr)
+               return walkexpr(n, init)
 
        case ir.ORUNESTR:
                a := nodnil()
@@ -1473,7 +1518,7 @@ opswitch:
                        a = ir.Nod(ir.OADDR, temp(t), nil)
                }
                // intstring(*[4]byte, rune)
-               n = mkcall("intstring", n.Type(), init, a, conv(n.Left(), types.Types[types.TINT64]))
+               return mkcall("intstring", n.Type(), init, a, conv(n.Left(), types.Types[types.TINT64]))
 
        case ir.OBYTES2STR, ir.ORUNES2STR:
                a := nodnil()
@@ -1484,25 +1529,24 @@ opswitch:
                }
                if n.Op() == ir.ORUNES2STR {
                        // slicerunetostring(*[32]byte, []rune) string
-                       n = mkcall("slicerunetostring", n.Type(), init, a, n.Left())
-               } else {
-                       // slicebytetostring(*[32]byte, ptr *byte, n int) string
-                       n.SetLeft(cheapexpr(n.Left(), init))
-                       ptr, len := backingArrayPtrLen(n.Left())
-                       n = mkcall("slicebytetostring", n.Type(), init, a, ptr, len)
+                       return mkcall("slicerunetostring", n.Type(), init, a, n.Left())
                }
+               // slicebytetostring(*[32]byte, ptr *byte, n int) string
+               n.SetLeft(cheapexpr(n.Left(), init))
+               ptr, len := backingArrayPtrLen(n.Left())
+               return mkcall("slicebytetostring", n.Type(), init, a, ptr, len)
 
        case ir.OBYTES2STRTMP:
                n.SetLeft(walkexpr(n.Left(), init))
                if !instrumenting {
                        // Let the backend handle OBYTES2STRTMP directly
                        // to avoid a function call to slicebytetostringtmp.
-                       break
+                       return n
                }
                // slicebytetostringtmp(ptr *byte, n int) string
                n.SetLeft(cheapexpr(n.Left(), init))
                ptr, len := backingArrayPtrLen(n.Left())
-               n = mkcall("slicebytetostringtmp", n.Type(), init, ptr, len)
+               return mkcall("slicebytetostringtmp", n.Type(), init, ptr, len)
 
        case ir.OSTR2BYTES:
                s := n.Left()
@@ -1534,8 +1578,7 @@ opswitch:
                        slice := ir.NodAt(n.Pos(), ir.OSLICEARR, p, nil)
                        slice.SetType(n.Type())
                        slice.SetTypecheck(1)
-                       n = walkexpr(slice, init)
-                       break
+                       return walkexpr(slice, init)
                }
 
                a := nodnil()
@@ -1545,7 +1588,7 @@ opswitch:
                        a = ir.Nod(ir.OADDR, temp(t), nil)
                }
                // stringtoslicebyte(*32[byte], string) []byte
-               n = mkcall("stringtoslicebyte", n.Type(), init, a, conv(s, types.Types[types.TSTRING]))
+               return mkcall("stringtoslicebyte", n.Type(), init, a, conv(s, types.Types[types.TSTRING]))
 
        case ir.OSTR2BYTESTMP:
                // []byte(string) conversion that creates a slice
@@ -1556,6 +1599,7 @@ opswitch:
                // The only such case today is:
                // for i, c := range []byte(string)
                n.SetLeft(walkexpr(n.Left(), init))
+               return n
 
        case ir.OSTR2RUNES:
                a := nodnil()
@@ -1565,7 +1609,7 @@ opswitch:
                        a = ir.Nod(ir.OADDR, temp(t), nil)
                }
                // stringtoslicerune(*[32]rune, string) []rune
-               n = mkcall("stringtoslicerune", n.Type(), init, a, conv(n.Left(), types.Types[types.TSTRING]))
+               return mkcall("stringtoslicerune", n.Type(), init, a, conv(n.Left(), types.Types[types.TSTRING]))
 
        case ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT, ir.OSTRUCTLIT, ir.OPTRLIT:
                if isStaticCompositeLiteral(n) && !canSSAType(n.Type()) {
@@ -1573,55 +1617,29 @@ opswitch:
                        // Make direct reference to the static data. See issue 12841.
                        vstat := readonlystaticname(n.Type())
                        fixedlit(inInitFunction, initKindStatic, n, vstat, init)
-                       n = vstat
-                       n = typecheck(n, ctxExpr)
-                       break
+                       return typecheck(vstat, ctxExpr)
                }
                var_ := temp(n.Type())
                anylit(n, var_, init)
-               n = var_
+               return var_
 
        case ir.OSEND:
                n1 := n.Right()
                n1 = assignconv(n1, n.Left().Type().Elem(), "chan send")
                n1 = walkexpr(n1, init)
                n1 = ir.Nod(ir.OADDR, n1, nil)
-               n = mkcall1(chanfn("chansend1", 2, n.Left().Type()), nil, init, n.Left(), n1)
+               return mkcall1(chanfn("chansend1", 2, n.Left().Type()), nil, init, n.Left(), n1)
 
        case ir.OCLOSURE:
-               n = walkclosure(n, init)
+               return walkclosure(n, init)
 
        case ir.OCALLPART:
-               n = walkpartialcall(n.(*ir.CallPartExpr), init)
-       }
-
-       // Expressions that are constant at run time but not
-       // considered const by the language spec are not turned into
-       // constants until walk. For example, if n is y%1 == 0, the
-       // walk of y%1 may have replaced it by 0.
-       // Check whether n with its updated args is itself now a constant.
-       t := n.Type()
-       n = evalConst(n)
-       if n.Type() != t {
-               base.Fatalf("evconst changed Type: %v had type %v, now %v", n, t, n.Type())
-       }
-       if n.Op() == ir.OLITERAL {
-               n = typecheck(n, ctxExpr)
-               // Emit string symbol now to avoid emitting
-               // any concurrently during the backend.
-               if v := n.Val(); v.Kind() == constant.String {
-                       _ = stringsym(n.Pos(), constant.StringVal(v))
-               }
-       }
-
-       updateHasCall(n)
-
-       if base.Flag.LowerW != 0 && n != nil {
-               ir.Dump("after walk expr", n)
+               return walkpartialcall(n.(*ir.CallPartExpr), init)
        }
 
-       base.Pos = lno
-       return n
+       // No return! Each case must return (or panic),
+       // to avoid confusion about what gets returned
+       // in the presence of type assertions.
 }
 
 // markTypeUsedInInterface marks that type t is converted to an interface.