mirror of
https://github.com/golang/go
synced 2024-10-05 20:31:20 -06:00
[dev.ssa] cmd/compile: implement len(map)
Implement len(map) values. Change-Id: If92be96ec9a7a86aeb3ce566d6758aab01c2fa7d Reviewed-on: https://go-review.googlesource.com/13961 Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
44d87035b6
commit
e0e4068c6e
@ -1440,8 +1440,7 @@ func (s *state) expr(n *Node) *ssa.Value {
|
|||||||
case n.Left.Type.IsString(): // string; not reachable for OCAP
|
case n.Left.Type.IsString(): // string; not reachable for OCAP
|
||||||
return s.newValue1(ssa.OpStringLen, Types[TINT], s.expr(n.Left))
|
return s.newValue1(ssa.OpStringLen, Types[TINT], s.expr(n.Left))
|
||||||
case n.Left.Type.IsMap():
|
case n.Left.Type.IsMap():
|
||||||
s.Unimplementedf("unhandled len(map)")
|
return s.lenMap(n, s.expr(n.Left))
|
||||||
return nil
|
|
||||||
case n.Left.Type.IsChan():
|
case n.Left.Type.IsChan():
|
||||||
if n.Op == OCAP {
|
if n.Op == OCAP {
|
||||||
s.Unimplementedf("unhandled cap(chan)")
|
s.Unimplementedf("unhandled cap(chan)")
|
||||||
@ -1998,6 +1997,41 @@ func (s *state) uintTofloat(cvttab *u2fcvtTab, n *Node, x *ssa.Value, ft, tt *Ty
|
|||||||
return s.variable(n, n.Type)
|
return s.variable(n, n.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *state) lenMap(n *Node, x *ssa.Value) *ssa.Value {
|
||||||
|
// if n == nil {
|
||||||
|
// return 0
|
||||||
|
// } else {
|
||||||
|
// return *((*int)n)
|
||||||
|
// }
|
||||||
|
lenType := n.Type
|
||||||
|
cmp := s.newValue2(ssa.OpEqPtr, Types[TBOOL], x, s.zeroVal(lenType))
|
||||||
|
b := s.endBlock()
|
||||||
|
b.Kind = ssa.BlockIf
|
||||||
|
b.Control = cmp
|
||||||
|
b.Likely = ssa.BranchUnlikely
|
||||||
|
|
||||||
|
bThen := s.f.NewBlock(ssa.BlockPlain)
|
||||||
|
bElse := s.f.NewBlock(ssa.BlockPlain)
|
||||||
|
bAfter := s.f.NewBlock(ssa.BlockPlain)
|
||||||
|
|
||||||
|
// length of a nil map is zero
|
||||||
|
addEdge(b, bThen)
|
||||||
|
s.startBlock(bThen)
|
||||||
|
s.vars[n] = s.zeroVal(lenType)
|
||||||
|
s.endBlock()
|
||||||
|
addEdge(bThen, bAfter)
|
||||||
|
|
||||||
|
// the length is stored in the first word
|
||||||
|
addEdge(b, bElse)
|
||||||
|
s.startBlock(bElse)
|
||||||
|
s.vars[n] = s.newValue2(ssa.OpLoad, lenType, x, s.mem())
|
||||||
|
s.endBlock()
|
||||||
|
addEdge(bElse, bAfter)
|
||||||
|
|
||||||
|
s.startBlock(bAfter)
|
||||||
|
return s.variable(n, lenType)
|
||||||
|
}
|
||||||
|
|
||||||
// checkgoto checks that a goto from from to to does not
|
// checkgoto checks that a goto from from to to does not
|
||||||
// jump into a block or jump over variable declarations.
|
// jump into a block or jump over variable declarations.
|
||||||
// It is a copy of checkgoto in the pre-SSA backend,
|
// It is a copy of checkgoto in the pre-SSA backend,
|
||||||
|
47
src/cmd/compile/internal/gc/testdata/map_ssa.go
vendored
Normal file
47
src/cmd/compile/internal/gc/testdata/map_ssa.go
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// map_ssa.go tests map operations.
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
var failed = false
|
||||||
|
|
||||||
|
func lenMap_ssa(v map[int]int) int {
|
||||||
|
switch { // prevent inlining
|
||||||
|
|
||||||
|
}
|
||||||
|
return len(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testLenMap() {
|
||||||
|
|
||||||
|
v := make(map[int]int)
|
||||||
|
v[0] = 0
|
||||||
|
v[1] = 0
|
||||||
|
v[2] = 0
|
||||||
|
|
||||||
|
if want, got := 3, lenMap_ssa(v); got != want {
|
||||||
|
fmt.Printf("expected len(map) = %d, got %d", want, got)
|
||||||
|
failed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testLenNilMap() {
|
||||||
|
|
||||||
|
var v map[int]int
|
||||||
|
if want, got := 0, lenMap_ssa(v); got != want {
|
||||||
|
fmt.Printf("expected len(nil) = %d, got %d", want, got)
|
||||||
|
failed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func main() {
|
||||||
|
testLenMap()
|
||||||
|
testLenNilMap()
|
||||||
|
|
||||||
|
if failed {
|
||||||
|
panic("failed")
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,7 @@
|
|||||||
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// string_ssa.go tests string operations.
|
// string_ssa.go tests string operations.
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user