diff --git a/src/cmd/compile/internal/walk/assign.go b/src/cmd/compile/internal/walk/assign.go index 9350c389c16..9b09e097fac 100644 --- a/src/cmd/compile/internal/walk/assign.go +++ b/src/cmd/compile/internal/walk/assign.go @@ -157,7 +157,7 @@ func walkAssignMapRead(init *ir.Nodes, n *ir.AssignListStmt) ir.Node { t := r.X.Type() fast := mapfast(t) - key := mapKeyArg(fast, r, r.Index) + key := mapKeyArg(fast, r, r.Index, false) // from: // a,b = m[i] diff --git a/src/cmd/compile/internal/walk/builtin.go b/src/cmd/compile/internal/walk/builtin.go index d0aaee03d59..b25627bd224 100644 --- a/src/cmd/compile/internal/walk/builtin.go +++ b/src/cmd/compile/internal/walk/builtin.go @@ -214,7 +214,7 @@ func walkDelete(init *ir.Nodes, n *ir.CallExpr) ir.Node { t := map_.Type() fast := mapfast(t) - key = mapKeyArg(fast, n, key) + key = mapKeyArg(fast, n, key, false) return mkcall1(mapfndel(mapdelete[fast], t), nil, init, reflectdata.TypePtr(t), map_, key) } diff --git a/src/cmd/compile/internal/walk/expr.go b/src/cmd/compile/internal/walk/expr.go index 43201dbd3d4..4c1e7adddd7 100644 --- a/src/cmd/compile/internal/walk/expr.go +++ b/src/cmd/compile/internal/walk/expr.go @@ -723,21 +723,23 @@ func walkIndex(n *ir.IndexExpr, init *ir.Nodes) ir.Node { } // mapKeyArg returns an expression for key that is suitable to be passed -// as the key argument for mapaccess and mapdelete functions. +// as the key argument for runtime map* functions. // n is is the map indexing or delete Node (to provide Pos). -// Note: this is not used for mapassign, which does distinguish pointer vs. -// integer key. -func mapKeyArg(fast int, n, key ir.Node) ir.Node { - switch fast { - case mapslow: +func mapKeyArg(fast int, n, key ir.Node, assigned bool) ir.Node { + if fast == mapslow { // standard version takes key by reference. - // order.expr made sure key is addressable. + // orderState.expr made sure key is addressable. return typecheck.NodAddr(key) + } + if assigned { + // mapassign does distinguish pointer vs. integer key. + return key + } + // mapaccess and mapdelete don't distinguish pointer vs. integer key. + switch fast { case mapfast32ptr: - // mapaccess and mapdelete don't distinguish pointer vs. integer key. return ir.NewConvExpr(n.Pos(), ir.OCONVNOP, types.Types[types.TUINT32], key) case mapfast64ptr: - // mapaccess and mapdelete don't distinguish pointer vs. integer key. return ir.NewConvExpr(n.Pos(), ir.OCONVNOP, types.Types[types.TUINT64], key) default: // fast version takes key by value. @@ -746,34 +748,27 @@ func mapKeyArg(fast int, n, key ir.Node) ir.Node { } // walkIndexMap walks an OINDEXMAP node. +// It replaces m[k] with *map{access1,assign}(maptype, m, &k) func walkIndexMap(n *ir.IndexExpr, init *ir.Nodes) ir.Node { - // Replace m[k] with *map{access1,assign}(maptype, m, &k) n.X = walkExpr(n.X, init) n.Index = walkExpr(n.Index, init) map_ := n.X - key := n.Index t := map_.Type() - var call *ir.CallExpr - if n.Assigned { - // This m[k] expression is on the left-hand side of an assignment. - fast := mapfast(t) - if fast == mapslow { - // standard version takes key by reference. - // order.expr made sure key is addressable. - key = typecheck.NodAddr(key) - } - call = mkcall1(mapfn(mapassign[fast], t, false), nil, init, reflectdata.TypePtr(t), map_, key) - } else { - // m[k] is not the target of an assignment. - fast := mapfast(t) - key = mapKeyArg(fast, n, key) - if w := t.Elem().Size(); w <= zeroValSize { - call = mkcall1(mapfn(mapaccess1[fast], t, false), types.NewPtr(t.Elem()), init, reflectdata.TypePtr(t), map_, key) - } else { - z := reflectdata.ZeroAddr(w) - call = mkcall1(mapfn("mapaccess1_fat", t, true), types.NewPtr(t.Elem()), init, reflectdata.TypePtr(t), map_, key, z) - } + fast := mapfast(t) + key := mapKeyArg(fast, n, n.Index, n.Assigned) + args := []ir.Node{reflectdata.TypePtr(t), map_, key} + + var mapFn ir.Node + switch { + case n.Assigned: + mapFn = mapfn(mapassign[fast], t, false) + case t.Elem().Size() > zeroValSize: + args = append(args, reflectdata.ZeroAddr(t.Elem().Size())) + mapFn = mapfn("mapaccess1_fat", t, true) + default: + mapFn = mapfn(mapaccess1[fast], t, false) } + call := mkcall1(mapFn, nil, init, args...) call.SetType(types.NewPtr(t.Elem())) call.MarkNonNil() // mapaccess1* and mapassign always return non-nil pointers. star := ir.NewStarExpr(base.Pos, call)