Commit 1c2bdfb7 authored by Matthew Dempsky's avatar Matthew Dempsky

cmd/compile: add Key, FieldSlice, and SetFields helpers

Allows safely eliminating more direct uses of Type's Type and Down
fields.

Passes toolstash -cmp.

Change-Id: I5c17fe541a0473c3cd2978d8314c4ab759079a61
Reviewed-on: https://go-review.googlesource.com/20541
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 0b281872
...@@ -223,7 +223,7 @@ func dowidth(t *Type) { ...@@ -223,7 +223,7 @@ func dowidth(t *Type) {
w = int64(Widthptr) w = int64(Widthptr)
checkwidth(t.Type) checkwidth(t.Type)
checkwidth(t.Down) checkwidth(t.Key())
case TFORW: // should have been filled in case TFORW: // should have been filled in
if !t.Broke { if !t.Broke {
......
...@@ -534,8 +534,8 @@ func (p *exporter) typ(t *Type) { ...@@ -534,8 +534,8 @@ func (p *exporter) typ(t *Type) {
case TMAP: case TMAP:
p.tag(mapTag) p.tag(mapTag)
p.typ(t.Down) // key p.typ(t.Key()) // key
p.typ(t.Type) // val p.typ(t.Type) // val
case TCHAN: case TCHAN:
p.tag(chanTag) p.tag(chanTag)
......
...@@ -827,12 +827,11 @@ func tostruct0(t *Type, l []*Node) { ...@@ -827,12 +827,11 @@ func tostruct0(t *Type, l []*Node) {
Fatalf("struct expected") Fatalf("struct expected")
} }
tp := &t.Type var fields []*Type
for _, n := range l { for _, n := range l {
f := structfield(n) fields = append(fields, structfield(n))
*tp = f
tp = &f.Down
} }
t.SetFields(fields)
for f, it := IterFields(t); f != nil && !t.Broke; f = it.Next() { for f, it := IterFields(t); f != nil && !t.Broke; f = it.Next() {
if f.Broke { if f.Broke {
...@@ -849,14 +848,12 @@ func tostruct0(t *Type, l []*Node) { ...@@ -849,14 +848,12 @@ func tostruct0(t *Type, l []*Node) {
} }
func tofunargs(l []*Node) *Type { func tofunargs(l []*Node) *Type {
var f *Type
t := typ(TSTRUCT) t := typ(TSTRUCT)
t.Funarg = true t.Funarg = true
tp := &t.Type var fields []*Type
for _, n := range l { for _, n := range l {
f = structfield(n) f := structfield(n)
f.Funarg = true f.Funarg = true
// esc.go needs to find f given a PPARAM to add the tag. // esc.go needs to find f given a PPARAM to add the tag.
...@@ -864,9 +861,9 @@ func tofunargs(l []*Node) *Type { ...@@ -864,9 +861,9 @@ func tofunargs(l []*Node) *Type {
n.Left.Name.Param.Field = f n.Left.Name.Param.Field = f
} }
*tp = f fields = append(fields, f)
tp = &f.Down
} }
t.SetFields(fields)
for f, it := IterFields(t); f != nil && !t.Broke; f = it.Next() { for f, it := IterFields(t); f != nil && !t.Broke; f = it.Next() {
if f.Broke { if f.Broke {
...@@ -955,7 +952,7 @@ func tointerface0(t *Type, l []*Node) *Type { ...@@ -955,7 +952,7 @@ func tointerface0(t *Type, l []*Node) *Type {
Fatalf("interface expected") Fatalf("interface expected")
} }
tp := &t.Type var fields []*Type
for _, n := range l { for _, n := range l {
f := interfacefield(n) f := interfacefield(n)
...@@ -969,14 +966,13 @@ func tointerface0(t *Type, l []*Node) *Type { ...@@ -969,14 +966,13 @@ func tointerface0(t *Type, l []*Node) *Type {
if f.Sym != nil { if f.Sym != nil {
f.Nname = newname(f.Sym) f.Nname = newname(f.Sym)
} }
*tp = f fields = append(fields, f)
tp = &f.Down
} }
} else { } else {
*tp = f fields = append(fields, f)
tp = &f.Down
} }
} }
t.SetFields(fields)
for f, it := IterFields(t); f != nil && !t.Broke; f = it.Next() { for f, it := IterFields(t); f != nil && !t.Broke; f = it.Next() {
if f.Broke { if f.Broke {
......
...@@ -580,7 +580,7 @@ func typefmt(t *Type, flag int) string { ...@@ -580,7 +580,7 @@ func typefmt(t *Type, flag int) string {
return fmt.Sprintf("chan %v", t.Type) return fmt.Sprintf("chan %v", t.Type)
case TMAP: case TMAP:
return fmt.Sprintf("map[%v]%v", t.Down, t.Type) return fmt.Sprintf("map[%v]%v", t.Key(), t.Type)
case TINTER: case TINTER:
var buf bytes.Buffer var buf bytes.Buffer
...@@ -645,15 +645,15 @@ func typefmt(t *Type, flag int) string { ...@@ -645,15 +645,15 @@ func typefmt(t *Type, flag int) 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 fmt.Sprintf("map.bucket[%v]%v", t.Map.Down, t.Map.Type) return fmt.Sprintf("map.bucket[%v]%v", t.Map.Key(), t.Map.Type)
} }
if t.Map.Hmap == t { if t.Map.Hmap == t {
return fmt.Sprintf("map.hdr[%v]%v", t.Map.Down, t.Map.Type) return fmt.Sprintf("map.hdr[%v]%v", t.Map.Key(), t.Map.Type)
} }
if t.Map.Hiter == t { if t.Map.Hiter == t {
return fmt.Sprintf("map.iter[%v]%v", t.Map.Down, t.Map.Type) return fmt.Sprintf("map.iter[%v]%v", t.Map.Key(), t.Map.Type)
} }
Yyerror("unknown internal map type") Yyerror("unknown internal map type")
......
...@@ -56,7 +56,7 @@ func typecheckrange(n *Node) { ...@@ -56,7 +56,7 @@ func typecheckrange(n *Node) {
t2 = t.Type t2 = t.Type
case TMAP: case TMAP:
t1 = t.Down t1 = t.Key()
t2 = t.Type t2 = t.Type
case TCHAN: case TCHAN:
...@@ -228,12 +228,12 @@ func walkrange(n *Node) { ...@@ -228,12 +228,12 @@ func walkrange(n *Node) {
hit := prealloc[n] hit := prealloc[n]
hit.Type = th hit.Type = th
n.Left = nil n.Left = nil
keyname := newname(th.Type.Sym) // depends on layout of iterator struct. See reflect.go:hiter keyname := newname(th.Field(0).Sym) // depends on layout of iterator struct. See reflect.go:hiter
valname := newname(th.Type.Down.Sym) // ditto valname := newname(th.Field(1).Sym) // ditto
fn := syslook("mapiterinit") fn := syslook("mapiterinit")
substArgTypes(&fn, t.Down, t.Type, th) substArgTypes(&fn, t.Key(), t.Type, 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, Nod(ODOT, hit, keyname), nodnil()) n.Left = Nod(ONE, Nod(ODOT, hit, keyname), nodnil())
......
...@@ -75,7 +75,7 @@ func mapbucket(t *Type) *Type { ...@@ -75,7 +75,7 @@ func mapbucket(t *Type) *Type {
} }
bucket := typ(TSTRUCT) bucket := typ(TSTRUCT)
keytype := t.Down keytype := t.Key()
valtype := t.Type valtype := t.Type
dowidth(keytype) dowidth(keytype)
dowidth(valtype) dowidth(valtype)
...@@ -119,7 +119,7 @@ func mapbucket(t *Type) *Type { ...@@ -119,7 +119,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.Down.Align) > Widthptr { if int(t.Type.Align) > Widthptr || int(t.Key().Align) > Widthptr {
field = append(field, makefield("pad", Types[TUINTPTR])) field = append(field, makefield("pad", Types[TUINTPTR]))
} }
...@@ -130,7 +130,7 @@ func mapbucket(t *Type) *Type { ...@@ -130,7 +130,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.Down) && t.Type.Width <= MAXKEYSIZE && t.Down.Width <= MAXVALSIZE { if !haspointers(t.Type) && !haspointers(t.Key()) && t.Type.Width <= MAXVALSIZE && t.Key().Width <= MAXKEYSIZE {
otyp = Types[TUINTPTR] otyp = Types[TUINTPTR]
} }
ovf := makefield("overflow", otyp) ovf := makefield("overflow", otyp)
...@@ -139,11 +139,7 @@ func mapbucket(t *Type) *Type { ...@@ -139,11 +139,7 @@ func mapbucket(t *Type) *Type {
// link up fields // link up fields
bucket.Noalg = true bucket.Noalg = true
bucket.Local = t.Local bucket.Local = t.Local
bucket.Type = field[0] bucket.SetFields(field[:])
for n := int32(0); n < int32(len(field)-1); n++ {
field[n].Down = field[n+1]
}
field[len(field)-1].Down = nil
dowidth(bucket) dowidth(bucket)
// Double-check that overflow field is final memory in struct, // Double-check that overflow field is final memory in struct,
...@@ -179,11 +175,7 @@ func hmap(t *Type) *Type { ...@@ -179,11 +175,7 @@ func hmap(t *Type) *Type {
h := typ(TSTRUCT) h := typ(TSTRUCT)
h.Noalg = true h.Noalg = true
h.Local = t.Local h.Local = t.Local
h.Type = field[0] h.SetFields(field[:])
for n := int32(0); n < int32(len(field)-1); n++ {
field[n].Down = field[n+1]
}
field[len(field)-1].Down = nil
dowidth(h) dowidth(h)
t.Hmap = h t.Hmap = h
h.Map = t h.Map = t
...@@ -212,8 +204,7 @@ func hiter(t *Type) *Type { ...@@ -212,8 +204,7 @@ func hiter(t *Type) *Type {
// } // }
// must match ../../../../runtime/hashmap.go:hiter. // must match ../../../../runtime/hashmap.go:hiter.
var field [12]*Type var field [12]*Type
field[0] = makefield("key", Ptrto(t.Down)) field[0] = makefield("key", Ptrto(t.Key()))
field[1] = makefield("val", Ptrto(t.Type)) field[1] = makefield("val", Ptrto(t.Type))
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)))
...@@ -228,13 +219,8 @@ func hiter(t *Type) *Type { ...@@ -228,13 +219,8 @@ func hiter(t *Type) *Type {
// build iterator struct holding the above fields // build iterator struct holding the above fields
i := typ(TSTRUCT) i := typ(TSTRUCT)
i.Noalg = true i.Noalg = true
i.Type = field[0] i.SetFields(field[:])
for n := int32(0); n < int32(len(field)-1); n++ {
field[n].Down = field[n+1]
}
field[len(field)-1].Down = nil
dowidth(i) dowidth(i)
if i.Width != int64(12*Widthptr) { if i.Width != int64(12*Widthptr) {
Yyerror("hash_iter size not correct %d %d", i.Width, 12*Widthptr) Yyerror("hash_iter size not correct %d %d", i.Width, 12*Widthptr)
...@@ -1124,8 +1110,7 @@ ok: ...@@ -1124,8 +1110,7 @@ ok:
// ../../../../runtime/type.go:/mapType // ../../../../runtime/type.go:/mapType
case TMAP: case TMAP:
s1 := dtypesym(t.Down) s1 := dtypesym(t.Key())
s2 := dtypesym(t.Type) s2 := dtypesym(t.Type)
s3 := dtypesym(mapbucket(t)) s3 := dtypesym(mapbucket(t))
s4 := dtypesym(hmap(t)) s4 := dtypesym(hmap(t))
...@@ -1134,11 +1119,11 @@ ok: ...@@ -1134,11 +1119,11 @@ ok:
ot = dsymptr(s, ot, s2, 0) ot = dsymptr(s, ot, s2, 0)
ot = dsymptr(s, ot, s3, 0) ot = dsymptr(s, ot, s3, 0)
ot = dsymptr(s, ot, s4, 0) ot = dsymptr(s, ot, s4, 0)
if t.Down.Width > MAXKEYSIZE { if t.Key().Width > MAXKEYSIZE {
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.Down.Width)) ot = duint8(s, ot, uint8(t.Key().Width))
ot = duint8(s, ot, 0) // not indirect ot = duint8(s, ot, 0) // not indirect
} }
...@@ -1151,8 +1136,8 @@ ok: ...@@ -1151,8 +1136,8 @@ ok:
} }
ot = duint16(s, ot, uint16(mapbucket(t).Width)) ot = duint16(s, ot, uint16(mapbucket(t).Width))
ot = duint8(s, ot, uint8(obj.Bool2int(isreflexive(t.Down)))) ot = duint8(s, ot, uint8(obj.Bool2int(isreflexive(t.Key()))))
ot = duint8(s, ot, uint8(obj.Bool2int(needkeyupdate(t.Down)))) ot = duint8(s, ot, uint8(obj.Bool2int(needkeyupdate(t.Key()))))
ot = dextratype(s, ot, t, 0) ot = dextratype(s, ot, t, 0)
case TPTR32, TPTR64: case TPTR32, TPTR64:
......
...@@ -979,7 +979,7 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) { ...@@ -979,7 +979,7 @@ func maplit(ctxt int, n *Node, var_ *Node, init *Nodes) {
// build list of var[c] = expr. // build list of var[c] = expr.
// 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.Down) key = temp(var_.Type.Key())
val = temp(var_.Type.Type) val = temp(var_.Type.Type)
} }
......
...@@ -417,23 +417,9 @@ func (x methcmp) Less(i, j int) bool { ...@@ -417,23 +417,9 @@ func (x methcmp) Less(i, j int) bool {
} }
func sortinter(t *Type) *Type { func sortinter(t *Type) *Type {
if t.Type == nil || t.Type.Down == nil { s := t.FieldSlice()
return t sort.Sort(methcmp(s))
} t.SetFields(s)
var a []*Type
for f, it := IterFields(t); f != nil; f = it.Next() {
a = append(a, f)
}
sort.Sort(methcmp(a))
n := len(a) // n > 0 due to initial conditions.
for i := 0; i < n-1; i++ {
a[i].Down = a[i+1]
}
a[n-1].Down = nil
t.Type = a[0]
return t return t
} }
...@@ -740,12 +726,9 @@ func eqtype1(t1, t2 *Type, assumedEqual map[typePair]struct{}) bool { ...@@ -740,12 +726,9 @@ func eqtype1(t1, t2 *Type, assumedEqual map[typePair]struct{}) bool {
switch t1.Etype { switch t1.Etype {
case TINTER, TSTRUCT: case TINTER, TSTRUCT:
t1 = t1.Type t1, i1 := IterFields(t1)
t2 = t2.Type t2, i2 := IterFields(t2)
for ; t1 != nil && t2 != nil; t1, t2 = t1.Down, t2.Down { for ; t1 != nil && t2 != nil; t1, t2 = i1.Next(), i2.Next() {
if t1.Etype != TFIELD || t2.Etype != TFIELD {
Fatalf("struct/interface missing field: %v %v", t1, t2)
}
if t1.Sym != t2.Sym || t1.Embedded != t2.Embedded || !eqtype1(t1.Type, t2.Type, assumedEqual) || !eqnote(t1.Note, t2.Note) { if t1.Sym != t2.Sym || t1.Embedded != t2.Embedded || !eqtype1(t1.Type, t2.Type, assumedEqual) || !eqnote(t1.Note, t2.Note) {
return false return false
} }
...@@ -782,9 +765,14 @@ func eqtype1(t1, t2 *Type, assumedEqual map[typePair]struct{}) bool { ...@@ -782,9 +765,14 @@ func eqtype1(t1, t2 *Type, assumedEqual map[typePair]struct{}) bool {
if t1.Chan != t2.Chan { if t1.Chan != t2.Chan {
return false return false
} }
case TMAP:
if !eqtype1(t1.Key(), t2.Key(), assumedEqual) {
return false
}
} }
return eqtype1(t1.Down, t2.Down, assumedEqual) && eqtype1(t1.Type, t2.Type, assumedEqual) return eqtype1(t1.Type, t2.Type, assumedEqual)
} }
// Are t1 and t2 equal struct types when field names are ignored? // Are t1 and t2 equal struct types when field names are ignored?
...@@ -795,8 +783,8 @@ func eqtypenoname(t1 *Type, t2 *Type) bool { ...@@ -795,8 +783,8 @@ func eqtypenoname(t1 *Type, t2 *Type) bool {
return false return false
} }
t1 = t1.Type t1, i1 := IterFields(t1)
t2 = t2.Type t2, i2 := IterFields(t2)
for { for {
if !Eqtype(t1, t2) { if !Eqtype(t1, t2) {
return false return false
...@@ -804,8 +792,8 @@ func eqtypenoname(t1 *Type, t2 *Type) bool { ...@@ -804,8 +792,8 @@ func eqtypenoname(t1 *Type, t2 *Type) bool {
if t1 == nil { if t1 == nil {
return true return true
} }
t1 = t1.Down t1 = i1.Next()
t2 = t2.Down t2 = i2.Next()
} }
} }
...@@ -2635,13 +2623,13 @@ func isdirectiface(t *Type) bool { ...@@ -2635,13 +2623,13 @@ func isdirectiface(t *Type) bool {
TUNSAFEPTR: TUNSAFEPTR:
return true return true
// Array of 1 direct iface type can be direct.
case TARRAY: case TARRAY:
// Array of 1 direct iface type can be direct.
return t.Bound == 1 && isdirectiface(t.Type) return t.Bound == 1 && isdirectiface(t.Type)
// Struct with 1 field of direct iface type can be direct.
case TSTRUCT: case TSTRUCT:
return t.Type != nil && t.Type.Down == nil && isdirectiface(t.Type.Type) // Struct with 1 field of direct iface type can be direct.
return countfield(t) == 1 && isdirectiface(t.Field(0).Type)
} }
return false return false
......
...@@ -274,6 +274,12 @@ var recvsParamsResults = [3]func(*Type) *Type{ ...@@ -274,6 +274,12 @@ var recvsParamsResults = [3]func(*Type) *Type{
(*Type).Recvs, (*Type).Params, (*Type).Results, (*Type).Recvs, (*Type).Params, (*Type).Results,
} }
// Key returns the key type of map type t.
func (t *Type) Key() *Type {
t.wantEtype(TMAP)
return t.Down
}
// Field returns the i'th field/method of struct/interface type t. // Field returns the i'th field/method of struct/interface type t.
func (t *Type) Field(i int) *Type { func (t *Type) Field(i int) *Type {
// TODO: store fields in a slice so we can // TODO: store fields in a slice so we can
...@@ -294,6 +300,29 @@ func (t *Type) Field(i int) *Type { ...@@ -294,6 +300,29 @@ func (t *Type) Field(i int) *Type {
panic("not enough fields") panic("not enough fields")
} }
// FieldSlice returns a slice of containing all fields/methods of
// struct/interface type t.
func (t *Type) FieldSlice() []*Type {
var s []*Type
for f, it := IterFields(t); f != nil; f = it.Next() {
s = append(s, f)
}
return s
}
// SetFields sets struct/interface type t's fields/methods to fields.
func (t *Type) SetFields(fields []*Type) {
if t.Etype != TSTRUCT && t.Etype != TINTER {
Fatalf("SetFields: type %v does not have fields", t)
}
var next *Type
for i := len(fields) - 1; i >= 0; i-- {
fields[i].Down = next
next = fields[i]
}
t.Type = next
}
func (t *Type) Size() int64 { func (t *Type) Size() int64 {
dowidth(t) dowidth(t)
return t.Width return t.Width
......
...@@ -1021,9 +1021,9 @@ OpSwitch: ...@@ -1021,9 +1021,9 @@ OpSwitch:
case TMAP: case TMAP:
n.Etype = 0 n.Etype = 0
defaultlit(&n.Right, t.Down) defaultlit(&n.Right, t.Key())
if n.Right.Type != nil { if n.Right.Type != nil {
n.Right = assignconv(n.Right, t.Down, "map index") n.Right = assignconv(n.Right, t.Key(), "map index")
} }
n.Type = t.Type n.Type = t.Type
n.Op = OINDEXMAP n.Op = OINDEXMAP
...@@ -1460,9 +1460,9 @@ OpSwitch: ...@@ -1460,9 +1460,9 @@ OpSwitch:
return return
} }
t = n.List.First().Type.Type t = n.List.First().Type
l = t.Nname l = t.Field(0).Nname
r = t.Down.Nname r = t.Field(1).Nname
} else { } else {
if !twoarg(n) { if !twoarg(n) {
n.Type = nil n.Type = nil
...@@ -1575,7 +1575,7 @@ OpSwitch: ...@@ -1575,7 +1575,7 @@ OpSwitch:
return return
} }
args.SetIndex(1, assignconv(r, l.Type.Down, "delete")) args.SetIndex(1, assignconv(r, l.Type.Key(), "delete"))
break OpSwitch break OpSwitch
case OAPPEND: case OAPPEND:
...@@ -3028,10 +3028,10 @@ func typecheckcomplit(np **Node) { ...@@ -3028,10 +3028,10 @@ func typecheckcomplit(np **Node) {
} }
r = l.Left r = l.Left
pushtype(r, t.Down) pushtype(r, t.Key())
typecheck(&r, Erv) typecheck(&r, Erv)
defaultlit(&r, t.Down) defaultlit(&r, t.Key())
l.Left = assignconv(r, t.Down, "map key") l.Left = assignconv(r, t.Key(), "map key")
if l.Left.Op != OCONV { if l.Left.Op != OCONV {
keydup(l.Left, hash) keydup(l.Left, hash)
} }
......
...@@ -104,19 +104,21 @@ func unsafenmagic(nn *Node) *Node { ...@@ -104,19 +104,21 @@ func unsafenmagic(nn *Node) *Node {
goto bad goto bad
} }
var f [2]*Type
f[0] = typ(TFIELD)
f[0].Type = Types[TUINT8]
f[1] = typ(TFIELD)
f[1].Type = tr
// make struct { byte; T; } // make struct { byte; T; }
t := typ(TSTRUCT) t := typ(TSTRUCT)
t.SetFields(f[:])
t.Type = typ(TFIELD)
t.Type.Type = Types[TUINT8]
t.Type.Down = typ(TFIELD)
t.Type.Down.Type = tr
// compute struct widths // compute struct widths
dowidth(t) dowidth(t)
// the offset of T is its required alignment // the offset of T is its required alignment
v = t.Type.Down.Width v = t.Field(1).Width
goto yes goto yes
} }
......
...@@ -840,7 +840,7 @@ opswitch: ...@@ -840,7 +840,7 @@ opswitch:
t := r.Left.Type t := r.Left.Type
p := "" p := ""
if t.Type.Width <= 128 { // Check ../../runtime/hashmap.go:maxValueSize before changing. if t.Type.Width <= 128 { // Check ../../runtime/hashmap.go:maxValueSize before changing.
switch algtype(t.Down) { switch algtype(t.Key()) {
case AMEM32: case AMEM32:
p = "mapaccess2_fast32" p = "mapaccess2_fast32"
case AMEM64: case AMEM64:
...@@ -876,7 +876,7 @@ opswitch: ...@@ -876,7 +876,7 @@ opswitch:
// the boolean result of i.(T) is now untyped so we make it the // the boolean result of i.(T) is now untyped so we make it the
// same type as the variable on the lhs. // same type as the variable on the lhs.
if !isblank(n.List.Second()) { if !isblank(n.List.Second()) {
r.Type.Type.Down.Type = n.List.Second().Type r.Type.Field(1).Type = n.List.Second().Type
} }
n.Rlist.Set1(r) n.Rlist.Set1(r)
n.Op = OAS2FUNC n.Op = OAS2FUNC
...@@ -1247,7 +1247,7 @@ opswitch: ...@@ -1247,7 +1247,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.Type.Width <= 128 { // Check ../../runtime/hashmap.go:maxValueSize before changing.
switch algtype(t.Down) { switch algtype(t.Key()) {
case AMEM32: case AMEM32:
p = "mapaccess1_fast32" p = "mapaccess1_fast32"
case AMEM64: case AMEM64:
...@@ -1439,7 +1439,7 @@ opswitch: ...@@ -1439,7 +1439,7 @@ opswitch:
} }
fn := syslook("makemap") fn := syslook("makemap")
substArgTypes(&fn, hmap(t), mapbucket(t), t.Down, t.Type) 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) n = mkcall1(fn, n.Type, init, typename(n.Type), conv(n.Left, Types[TINT64]), a, r)
case OMAKESLICE: case OMAKESLICE:
...@@ -2690,7 +2690,7 @@ func mapfn(name string, t *Type) *Node { ...@@ -2690,7 +2690,7 @@ func mapfn(name string, t *Type) *Node {
Fatalf("mapfn %v", t) Fatalf("mapfn %v", t)
} }
fn := syslook(name) fn := syslook(name)
substArgTypes(&fn, t.Down, t.Type, t.Down, t.Type) substArgTypes(&fn, t.Key(), t.Type, t.Key(), t.Type)
return fn return fn
} }
...@@ -2699,7 +2699,7 @@ func mapfndel(name string, t *Type) *Node { ...@@ -2699,7 +2699,7 @@ func mapfndel(name string, t *Type) *Node {
Fatalf("mapfn %v", t) Fatalf("mapfn %v", t)
} }
fn := syslook(name) fn := syslook(name)
substArgTypes(&fn, t.Down, t.Type, t.Down) substArgTypes(&fn, t.Key(), t.Type, t.Key())
return fn return fn
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment