mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: encapsulate map value type
Passes toolstash -cmp. Change-Id: I83af544974e1e91e0810e13321afb3e665dcdf12 Reviewed-on: https://go-review.googlesource.com/21248 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
bf5f24b98e
commit
093a9a1f56
10 changed files with 40 additions and 33 deletions
|
|
@ -213,8 +213,7 @@ func dowidth(t *Type) {
|
||||||
|
|
||||||
case TMAP: // implemented as pointer
|
case TMAP: // implemented as pointer
|
||||||
w = int64(Widthptr)
|
w = int64(Widthptr)
|
||||||
|
checkwidth(t.Val())
|
||||||
checkwidth(t.Type)
|
|
||||||
checkwidth(t.Key())
|
checkwidth(t.Key())
|
||||||
|
|
||||||
case TFORW: // should have been filled in
|
case TFORW: // should have been filled in
|
||||||
|
|
|
||||||
|
|
@ -542,8 +542,8 @@ func (p *exporter) typ(t *Type) {
|
||||||
|
|
||||||
case TMAP:
|
case TMAP:
|
||||||
p.tag(mapTag)
|
p.tag(mapTag)
|
||||||
p.typ(t.Key()) // key
|
p.typ(t.Key())
|
||||||
p.typ(t.Type) // val
|
p.typ(t.Val())
|
||||||
|
|
||||||
case TCHAN:
|
case TCHAN:
|
||||||
p.tag(chanTag)
|
p.tag(chanTag)
|
||||||
|
|
|
||||||
|
|
@ -609,7 +609,7 @@ func typefmt(t *Type, flag FmtFlag) string {
|
||||||
return "chan " + t.Type.String()
|
return "chan " + t.Type.String()
|
||||||
|
|
||||||
case TMAP:
|
case TMAP:
|
||||||
return "map[" + t.Key().String() + "]" + t.Type.String()
|
return "map[" + t.Key().String() + "]" + t.Val().String()
|
||||||
|
|
||||||
case TINTER:
|
case TINTER:
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
@ -674,15 +674,15 @@ func typefmt(t *Type, flag FmtFlag) string {
|
||||||
// Format the bucket struct for map[x]y as map.bucket[x]y.
|
// Format the bucket struct for map[x]y as map.bucket[x]y.
|
||||||
// This avoids a recursive print that generates very long names.
|
// This avoids a recursive print that generates very long names.
|
||||||
if t.Map.Bucket == t {
|
if t.Map.Bucket == t {
|
||||||
return "map.bucket[" + t.Map.Key().String() + "]" + t.Map.Type.String()
|
return "map.bucket[" + t.Map.Key().String() + "]" + t.Map.Val().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.Map.Hmap == t {
|
if t.Map.Hmap == t {
|
||||||
return "map.hdr[" + t.Map.Key().String() + "]" + t.Map.Type.String()
|
return "map.hdr[" + t.Map.Key().String() + "]" + t.Map.Val().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.Map.Hiter == t {
|
if t.Map.Hiter == t {
|
||||||
return "map.iter[" + t.Map.Key().String() + "]" + t.Map.Type.String()
|
return "map.iter[" + t.Map.Key().String() + "]" + t.Map.Val().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
Yyerror("unknown internal map type")
|
Yyerror("unknown internal map type")
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ func typecheckrange(n *Node) {
|
||||||
|
|
||||||
case TMAP:
|
case TMAP:
|
||||||
t1 = t.Key()
|
t1 = t.Key()
|
||||||
t2 = t.Type
|
t2 = t.Val()
|
||||||
|
|
||||||
case TCHAN:
|
case TCHAN:
|
||||||
if t.Chan&Crecv == 0 {
|
if t.Chan&Crecv == 0 {
|
||||||
|
|
@ -231,7 +231,7 @@ func walkrange(n *Node) {
|
||||||
|
|
||||||
fn := syslook("mapiterinit")
|
fn := syslook("mapiterinit")
|
||||||
|
|
||||||
fn = substArgTypes(fn, t.Key(), t.Type, th)
|
fn = substArgTypes(fn, t.Key(), t.Val(), th)
|
||||||
init = append(init, mkcall1(fn, nil, nil, typename(t), ha, Nod(OADDR, hit, nil)))
|
init = append(init, mkcall1(fn, nil, nil, typename(t), ha, Nod(OADDR, hit, nil)))
|
||||||
n.Left = Nod(ONE, NodSym(ODOT, hit, keysym), nodnil())
|
n.Left = Nod(ONE, NodSym(ODOT, hit, keysym), nodnil())
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ func mapbucket(t *Type) *Type {
|
||||||
|
|
||||||
bucket := typ(TSTRUCT)
|
bucket := typ(TSTRUCT)
|
||||||
keytype := t.Key()
|
keytype := t.Key()
|
||||||
valtype := t.Type
|
valtype := t.Val()
|
||||||
dowidth(keytype)
|
dowidth(keytype)
|
||||||
dowidth(valtype)
|
dowidth(valtype)
|
||||||
if keytype.Width > MAXKEYSIZE {
|
if keytype.Width > MAXKEYSIZE {
|
||||||
|
|
@ -125,7 +125,7 @@ func mapbucket(t *Type) *Type {
|
||||||
// so if the struct needs 64-bit padding (because a key or value does)
|
// so if the struct needs 64-bit padding (because a key or value does)
|
||||||
// then it would end with an extra 32-bit padding field.
|
// then it would end with an extra 32-bit padding field.
|
||||||
// Preempt that by emitting the padding here.
|
// Preempt that by emitting the padding here.
|
||||||
if int(t.Type.Align) > Widthptr || int(t.Key().Align) > Widthptr {
|
if int(t.Val().Align) > Widthptr || int(t.Key().Align) > Widthptr {
|
||||||
field = append(field, makefield("pad", Types[TUINTPTR]))
|
field = append(field, makefield("pad", Types[TUINTPTR]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -136,7 +136,7 @@ func mapbucket(t *Type) *Type {
|
||||||
// the type of the overflow field to uintptr in this case.
|
// the type of the overflow field to uintptr in this case.
|
||||||
// See comment on hmap.overflow in ../../../../runtime/hashmap.go.
|
// See comment on hmap.overflow in ../../../../runtime/hashmap.go.
|
||||||
otyp := Ptrto(bucket)
|
otyp := Ptrto(bucket)
|
||||||
if !haspointers(t.Type) && !haspointers(t.Key()) && t.Type.Width <= MAXVALSIZE && t.Key().Width <= MAXKEYSIZE {
|
if !haspointers(t.Val()) && !haspointers(t.Key()) && t.Val().Width <= MAXVALSIZE && t.Key().Width <= MAXKEYSIZE {
|
||||||
otyp = Types[TUINTPTR]
|
otyp = Types[TUINTPTR]
|
||||||
}
|
}
|
||||||
ovf := makefield("overflow", otyp)
|
ovf := makefield("overflow", otyp)
|
||||||
|
|
@ -211,7 +211,7 @@ func hiter(t *Type) *Type {
|
||||||
// must match ../../../../runtime/hashmap.go:hiter.
|
// must match ../../../../runtime/hashmap.go:hiter.
|
||||||
var field [12]*Field
|
var field [12]*Field
|
||||||
field[0] = makefield("key", Ptrto(t.Key()))
|
field[0] = makefield("key", Ptrto(t.Key()))
|
||||||
field[1] = makefield("val", Ptrto(t.Type))
|
field[1] = makefield("val", Ptrto(t.Val()))
|
||||||
field[2] = makefield("t", Ptrto(Types[TUINT8]))
|
field[2] = makefield("t", Ptrto(Types[TUINT8]))
|
||||||
field[3] = makefield("h", Ptrto(hmap(t)))
|
field[3] = makefield("h", Ptrto(hmap(t)))
|
||||||
field[4] = makefield("buckets", Ptrto(mapbucket(t)))
|
field[4] = makefield("buckets", Ptrto(mapbucket(t)))
|
||||||
|
|
@ -1226,7 +1226,7 @@ ok:
|
||||||
// ../../../../runtime/type.go:/mapType
|
// ../../../../runtime/type.go:/mapType
|
||||||
case TMAP:
|
case TMAP:
|
||||||
s1 := dtypesym(t.Key())
|
s1 := dtypesym(t.Key())
|
||||||
s2 := dtypesym(t.Type)
|
s2 := dtypesym(t.Val())
|
||||||
s3 := dtypesym(mapbucket(t))
|
s3 := dtypesym(mapbucket(t))
|
||||||
s4 := dtypesym(hmap(t))
|
s4 := dtypesym(hmap(t))
|
||||||
ot = dcommontype(s, ot, t)
|
ot = dcommontype(s, ot, t)
|
||||||
|
|
@ -1242,11 +1242,11 @@ ok:
|
||||||
ot = duint8(s, ot, 0) // not indirect
|
ot = duint8(s, ot, 0) // not indirect
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.Type.Width > MAXVALSIZE {
|
if t.Val().Width > MAXVALSIZE {
|
||||||
ot = duint8(s, ot, uint8(Widthptr))
|
ot = duint8(s, ot, uint8(Widthptr))
|
||||||
ot = duint8(s, ot, 1) // indirect
|
ot = duint8(s, ot, 1) // indirect
|
||||||
} else {
|
} else {
|
||||||
ot = duint8(s, ot, uint8(t.Type.Width))
|
ot = duint8(s, ot, uint8(t.Val().Width))
|
||||||
ot = duint8(s, ot, 0) // not indirect
|
ot = duint8(s, ot, 0) // not indirect
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -860,7 +860,7 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
||||||
// build type [count]struct { a Tindex, b Tvalue }
|
// build type [count]struct { a Tindex, b Tvalue }
|
||||||
t := n.Type
|
t := n.Type
|
||||||
tk := t.Key()
|
tk := t.Key()
|
||||||
tv := t.Type
|
tv := t.Val()
|
||||||
|
|
||||||
syma := Lookup("a")
|
syma := Lookup("a")
|
||||||
symb := Lookup("b")
|
symb := Lookup("b")
|
||||||
|
|
@ -969,7 +969,7 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
|
||||||
// use temporary so that mapassign1 can have addressable key, val.
|
// use temporary so that mapassign1 can have addressable key, val.
|
||||||
if key == nil {
|
if key == nil {
|
||||||
key = temp(var_.Type.Key())
|
key = temp(var_.Type.Key())
|
||||||
val = temp(var_.Type.Type)
|
val = temp(var_.Type.Val())
|
||||||
}
|
}
|
||||||
|
|
||||||
setlineno(r.Left)
|
setlineno(r.Left)
|
||||||
|
|
|
||||||
|
|
@ -773,6 +773,7 @@ func eqtype1(t1, t2 *Type, assumedEqual map[typePair]struct{}) bool {
|
||||||
if !eqtype1(t1.Key(), t2.Key(), assumedEqual) {
|
if !eqtype1(t1.Key(), t2.Key(), assumedEqual) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
return eqtype1(t1.Val(), t2.Val(), assumedEqual)
|
||||||
}
|
}
|
||||||
|
|
||||||
return eqtype1(t1.Type, t2.Type, assumedEqual)
|
return eqtype1(t1.Type, t2.Type, assumedEqual)
|
||||||
|
|
|
||||||
|
|
@ -342,6 +342,12 @@ func (t *Type) Key() *Type {
|
||||||
return t.Down
|
return t.Down
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Val returns the value type of map type t.
|
||||||
|
func (t *Type) Val() *Type {
|
||||||
|
t.wantEtype(TMAP)
|
||||||
|
return t.Type
|
||||||
|
}
|
||||||
|
|
||||||
func (t *Type) Methods() *Fields {
|
func (t *Type) Methods() *Fields {
|
||||||
// TODO(mdempsky): Validate t?
|
// TODO(mdempsky): Validate t?
|
||||||
return &t.methods
|
return &t.methods
|
||||||
|
|
@ -524,9 +530,10 @@ func (t *Type) cmp(x *Type) ssa.Cmp {
|
||||||
|
|
||||||
switch t.Etype {
|
switch t.Etype {
|
||||||
case TMAP:
|
case TMAP:
|
||||||
if c := t.Down.cmp(x.Down); c != ssa.CMPeq {
|
if c := t.Key().cmp(x.Key()); c != ssa.CMPeq {
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
return t.Val().cmp(x.Val())
|
||||||
|
|
||||||
case TPTR32, TPTR64:
|
case TPTR32, TPTR64:
|
||||||
// No special cases for these two, they are handled
|
// No special cases for these two, they are handled
|
||||||
|
|
@ -614,7 +621,7 @@ func (t *Type) cmp(x *Type) ssa.Cmp {
|
||||||
panic(e)
|
panic(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Common element type comparison for TARRAY, TCHAN, TMAP, TPTR32, and TPTR64.
|
// Common element type comparison for TARRAY, TCHAN, TPTR32, and TPTR64.
|
||||||
return t.Type.cmp(x.Type)
|
return t.Type.cmp(x.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1026,7 +1026,7 @@ OpSwitch:
|
||||||
if n.Right.Type != nil {
|
if n.Right.Type != nil {
|
||||||
n.Right = assignconv(n.Right, t.Key(), "map index")
|
n.Right = assignconv(n.Right, t.Key(), "map index")
|
||||||
}
|
}
|
||||||
n.Type = t.Type
|
n.Type = t.Val()
|
||||||
n.Op = OINDEXMAP
|
n.Op = OINDEXMAP
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3021,10 +3021,10 @@ func typecheckcomplit(n *Node) *Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
r = l.Right
|
r = l.Right
|
||||||
pushtype(r, t.Type)
|
pushtype(r, t.Val())
|
||||||
r = typecheck(r, Erv)
|
r = typecheck(r, Erv)
|
||||||
r = defaultlit(r, t.Type)
|
r = defaultlit(r, t.Val())
|
||||||
l.Right = assignconv(r, t.Type, "map value")
|
l.Right = assignconv(r, t.Val(), "map value")
|
||||||
}
|
}
|
||||||
|
|
||||||
n.Op = OMAPLIT
|
n.Op = OMAPLIT
|
||||||
|
|
|
||||||
|
|
@ -835,7 +835,7 @@ opswitch:
|
||||||
r.Right = walkexpr(r.Right, init)
|
r.Right = walkexpr(r.Right, init)
|
||||||
t := r.Left.Type
|
t := r.Left.Type
|
||||||
p := ""
|
p := ""
|
||||||
if t.Type.Width <= 128 { // Check ../../runtime/hashmap.go:maxValueSize before changing.
|
if t.Val().Width <= 128 { // Check ../../runtime/hashmap.go:maxValueSize before changing.
|
||||||
switch algtype(t.Key()) {
|
switch algtype(t.Key()) {
|
||||||
case AMEM32:
|
case AMEM32:
|
||||||
p = "mapaccess2_fast32"
|
p = "mapaccess2_fast32"
|
||||||
|
|
@ -879,7 +879,7 @@ opswitch:
|
||||||
|
|
||||||
// don't generate a = *var if a is _
|
// don't generate a = *var if a is _
|
||||||
if !isblank(a) {
|
if !isblank(a) {
|
||||||
var_ := temp(Ptrto(t.Type))
|
var_ := temp(Ptrto(t.Val()))
|
||||||
var_.Typecheck = 1
|
var_.Typecheck = 1
|
||||||
n.List.SetIndex(0, var_)
|
n.List.SetIndex(0, var_)
|
||||||
n = walkexpr(n, init)
|
n = walkexpr(n, init)
|
||||||
|
|
@ -1200,7 +1200,7 @@ opswitch:
|
||||||
|
|
||||||
t := n.Left.Type
|
t := n.Left.Type
|
||||||
p := ""
|
p := ""
|
||||||
if t.Type.Width <= 128 { // Check ../../runtime/hashmap.go:maxValueSize before changing.
|
if t.Val().Width <= 128 { // Check ../../runtime/hashmap.go:maxValueSize before changing.
|
||||||
switch algtype(t.Key()) {
|
switch algtype(t.Key()) {
|
||||||
case AMEM32:
|
case AMEM32:
|
||||||
p = "mapaccess1_fast32"
|
p = "mapaccess1_fast32"
|
||||||
|
|
@ -1223,9 +1223,9 @@ opswitch:
|
||||||
p = "mapaccess1"
|
p = "mapaccess1"
|
||||||
}
|
}
|
||||||
|
|
||||||
n = mkcall1(mapfn(p, t), Ptrto(t.Type), init, typename(t), n.Left, key)
|
n = mkcall1(mapfn(p, t), Ptrto(t.Val()), init, typename(t), n.Left, key)
|
||||||
n = Nod(OIND, n, nil)
|
n = Nod(OIND, n, nil)
|
||||||
n.Type = t.Type
|
n.Type = t.Val()
|
||||||
n.Typecheck = 1
|
n.Typecheck = 1
|
||||||
|
|
||||||
case ORECV:
|
case ORECV:
|
||||||
|
|
@ -1393,7 +1393,7 @@ opswitch:
|
||||||
}
|
}
|
||||||
|
|
||||||
fn := syslook("makemap")
|
fn := syslook("makemap")
|
||||||
fn = substArgTypes(fn, hmap(t), mapbucket(t), t.Key(), t.Type)
|
fn = substArgTypes(fn, hmap(t), mapbucket(t), t.Key(), t.Val())
|
||||||
n = mkcall1(fn, n.Type, init, typename(n.Type), conv(n.Left, Types[TINT64]), a, r)
|
n = mkcall1(fn, n.Type, init, typename(n.Type), conv(n.Left, Types[TINT64]), a, r)
|
||||||
|
|
||||||
case OMAKESLICE:
|
case OMAKESLICE:
|
||||||
|
|
@ -2647,7 +2647,7 @@ func mapfn(name string, t *Type) *Node {
|
||||||
Fatalf("mapfn %v", t)
|
Fatalf("mapfn %v", t)
|
||||||
}
|
}
|
||||||
fn := syslook(name)
|
fn := syslook(name)
|
||||||
fn = substArgTypes(fn, t.Key(), t.Type, t.Key(), t.Type)
|
fn = substArgTypes(fn, t.Key(), t.Val(), t.Key(), t.Val())
|
||||||
return fn
|
return fn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2656,7 +2656,7 @@ func mapfndel(name string, t *Type) *Node {
|
||||||
Fatalf("mapfn %v", t)
|
Fatalf("mapfn %v", t)
|
||||||
}
|
}
|
||||||
fn := syslook(name)
|
fn := syslook(name)
|
||||||
fn = substArgTypes(fn, t.Key(), t.Type, t.Key())
|
fn = substArgTypes(fn, t.Key(), t.Val(), t.Key())
|
||||||
return fn
|
return fn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue