cmd/compile: add Type.Elem

This removes almost all direct access to
Type’s heavily overloaded Type field.

Mostly generated by eg, manually checked.

Significant manual changes:

* reflect.go's typPkg used Type indiscriminately.
  Use it only for specific etypes.
* gen.go's visitComponents contained a usage of Type
  with structs. Using Type for structs no longer
  occurs, and the Fatal contained therein has not triggered,
  so it has been axed.
* Scary code in cgen.go's cgen_slice is now explicitly scary.

Passes toolstash -cmp.

Change-Id: I2dbfb3c959da7ae239f964d83898c204affcabc6
Reviewed-on: https://go-review.googlesource.com/21331
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Josh Bleecher Snyder 2016-03-30 10:57:47 -07:00
parent 76e72691a0
commit 8640b51df8
23 changed files with 226 additions and 213 deletions

View File

@ -106,7 +106,7 @@ func algtype1(t *Type, bad **Type) int {
return ANOEQ return ANOEQ
} }
a := algtype1(t.Type, bad) a := algtype1(t.Elem(), bad)
switch a { switch a {
case AMEM: case AMEM:
return AMEM return AMEM
@ -203,7 +203,7 @@ func genhash(sym *Sym, t *Type) {
// An array of pure memory would be handled by the // An array of pure memory would be handled by the
// standard algorithm, so the element type must not be // standard algorithm, so the element type must not be
// pure memory. // pure memory.
hashel := hashfor(t.Type) hashel := hashfor(t.Elem())
n := Nod(ORANGE, nil, Nod(OIND, np, nil)) n := Nod(ORANGE, nil, Nod(OIND, np, nil))
ni := newname(Lookup("i")) ni := newname(Lookup("i"))
@ -519,7 +519,7 @@ func eqmem(p *Node, q *Node, field *Sym, size int64) *Node {
nx = typecheck(nx, Erv) nx = typecheck(nx, Erv)
ny = typecheck(ny, Erv) ny = typecheck(ny, Erv)
fn, needsize := eqmemfunc(size, nx.Type.Type) fn, needsize := eqmemfunc(size, nx.Type.Elem())
call := Nod(OCALL, fn, nil) call := Nod(OCALL, fn, nil)
call.List.Append(nx) call.List.Append(nx)
call.List.Append(ny) call.List.Append(ny)

View File

@ -176,11 +176,11 @@ func dowidth(t *Type) {
case TPTR32: case TPTR32:
w = 4 w = 4
checkwidth(t.Type) checkwidth(t.Elem())
case TPTR64: case TPTR64:
w = 8 w = 8
checkwidth(t.Type) checkwidth(t.Elem())
case TUNSAFEPTR: case TUNSAFEPTR:
w = int64(Widthptr) w = int64(Widthptr)
@ -194,7 +194,7 @@ func dowidth(t *Type) {
case TCHAN: // implemented as pointer case TCHAN: // implemented as pointer
w = int64(Widthptr) w = int64(Widthptr)
checkwidth(t.Type) checkwidth(t.Elem())
// make fake type to check later to // make fake type to check later to
// trigger channel argument check. // trigger channel argument check.
@ -204,7 +204,7 @@ func dowidth(t *Type) {
case TCHANARGS: case TCHANARGS:
t1 := t.Wrapped() t1 := t.Wrapped()
dowidth(t1) // just in case dowidth(t1) // just in case
if t1.Type.Width >= 1<<16 { if t1.Elem().Width >= 1<<16 {
Yyerror("channel element type too large (>64kB)") Yyerror("channel element type too large (>64kB)")
} }
t.Width = 1 t.Width = 1
@ -235,23 +235,23 @@ func dowidth(t *Type) {
t.Align = uint8(Widthptr) t.Align = uint8(Widthptr)
case TARRAY: case TARRAY:
if t.Type == nil { if t.Elem() == nil {
break break
} }
if t.IsArray() { if t.IsArray() {
dowidth(t.Type) dowidth(t.Elem())
if t.Type.Width != 0 { if t.Elem().Width != 0 {
cap := (uint64(Thearch.MAXWIDTH) - 1) / uint64(t.Type.Width) cap := (uint64(Thearch.MAXWIDTH) - 1) / uint64(t.Elem().Width)
if uint64(t.Bound) > cap { if uint64(t.Bound) > cap {
Yyerror("type %v larger than address space", Tconv(t, FmtLong)) Yyerror("type %v larger than address space", Tconv(t, FmtLong))
} }
} }
w = t.Bound * t.Type.Width w = t.Bound * t.Elem().Width
t.Align = t.Type.Align t.Align = t.Elem().Align
} else if t.Bound == -1 { } else if t.Bound == -1 {
w = int64(sizeof_Array) w = int64(sizeof_Array)
checkwidth(t.Type) checkwidth(t.Elem())
t.Align = uint8(Widthptr) t.Align = uint8(Widthptr)
} else if t.isDDDArray() { } else if t.isDDDArray() {
if !t.Broke { if !t.Broke {

View File

@ -512,7 +512,7 @@ func (p *exporter) typ(t *Type) {
} else { } else {
p.tag(sliceTag) p.tag(sliceTag)
} }
p.typ(t.Type) p.typ(t.Elem())
case TDDDFIELD: case TDDDFIELD:
// see p.param use of TDDDFIELD // see p.param use of TDDDFIELD
@ -525,7 +525,7 @@ func (p *exporter) typ(t *Type) {
case TPTR32, TPTR64: // could use Tptr but these are constants case TPTR32, TPTR64: // could use Tptr but these are constants
p.tag(pointerTag) p.tag(pointerTag)
p.typ(t.Type) p.typ(t.Elem())
case TFUNC: case TFUNC:
p.tag(signatureTag) p.tag(signatureTag)
@ -548,7 +548,7 @@ func (p *exporter) typ(t *Type) {
case TCHAN: case TCHAN:
p.tag(chanTag) p.tag(chanTag)
p.int(int(t.Chan)) p.int(int(t.Chan))
p.typ(t.Type) p.typ(t.Elem())
default: default:
Fatalf("exporter: unexpected type: %s (Etype = %d)", Tconv(t, 0), t.Etype) Fatalf("exporter: unexpected type: %s (Etype = %d)", Tconv(t, 0), t.Etype)
@ -636,7 +636,7 @@ func (p *exporter) fieldName(t *Field) {
func basetypeName(t *Type) string { func basetypeName(t *Type) string {
s := t.Sym s := t.Sym
if s == nil && Isptr[t.Etype] { if s == nil && Isptr[t.Etype] {
s = t.Type.Sym // deref s = t.Elem().Sym // deref
} }
if s != nil { if s != nil {
return s.Name return s.Name
@ -666,7 +666,7 @@ func (p *exporter) param(q *Field, n int, numbered bool) {
t := q.Type t := q.Type
if q.Isddd { if q.Isddd {
// create a fake type to encode ... just for the p.typ call // create a fake type to encode ... just for the p.typ call
t = typWrapper(TDDDFIELD, t.Type) t = typWrapper(TDDDFIELD, t.Elem())
} }
p.typ(t) p.typ(t)
if n > 0 { if n > 0 {

View File

@ -2214,14 +2214,14 @@ func stkof(n *Node) int64 {
return off return off
} }
if Isconst(n.Right, CTINT) { if Isconst(n.Right, CTINT) {
return off + t.Type.Width*n.Right.Val().U.(*Mpint).Int64() return off + t.Elem().Width*n.Right.Val().U.(*Mpint).Int64()
} }
return +1000 // on stack but not sure exactly where return +1000 // on stack but not sure exactly where
case OCALLMETH, OCALLINTER, OCALLFUNC: case OCALLMETH, OCALLINTER, OCALLFUNC:
t := n.Left.Type t := n.Left.Type
if Isptr[t.Etype] { if Isptr[t.Etype] {
t = t.Type t = t.Elem()
} }
f := t.Results().Field(0) f := t.Results().Field(0)
@ -2552,7 +2552,7 @@ func cgen_call(n *Node, proc int) {
func cgen_callret(n *Node, res *Node) { func cgen_callret(n *Node, res *Node) {
t := n.Left.Type t := n.Left.Type
if t.Etype == TPTR32 || t.Etype == TPTR64 { if t.Etype == TPTR32 || t.Etype == TPTR64 {
t = t.Type t = t.Elem()
} }
fp := t.Results().Field(0) fp := t.Results().Field(0)
@ -2576,7 +2576,7 @@ func cgen_callret(n *Node, res *Node) {
func cgen_aret(n *Node, res *Node) { func cgen_aret(n *Node, res *Node) {
t := n.Left.Type t := n.Left.Type
if Isptr[t.Etype] { if Isptr[t.Etype] {
t = t.Type t = t.Elem()
} }
fp := t.Results().Field(0) fp := t.Results().Field(0)
@ -2865,7 +2865,7 @@ func cgen_append(n, res *Node) {
Regfree(&rlen) Regfree(&rlen)
fn := syslook("growslice") fn := syslook("growslice")
fn = substArgTypes(fn, res.Type.Type, res.Type.Type) fn = substArgTypes(fn, res.Type.Elem(), res.Type.Elem())
Ginscall(fn, 0) Ginscall(fn, 0)
if Widthptr == 4 && Widthreg == 8 { if Widthptr == 4 && Widthreg == 8 {
@ -2945,7 +2945,7 @@ func cgen_append(n, res *Node) {
if i > 0 { if i > 0 {
Thearch.Gins(Thearch.Optoas(OADD, Types[TUINT]), Nodintconst(int64(i)), &r2) Thearch.Gins(Thearch.Optoas(OADD, Types[TUINT]), Nodintconst(int64(i)), &r2)
} }
w := res.Type.Type.Width w := res.Type.Elem().Width
if Thearch.AddIndex != nil && Thearch.AddIndex(&r2, w, &r1) { if Thearch.AddIndex != nil && Thearch.AddIndex(&r2, w, &r1) {
// r1 updated by back end // r1 updated by back end
} else if w == 1 { } else if w == 1 {
@ -2957,7 +2957,7 @@ func cgen_append(n, res *Node) {
Regfree(&r2) Regfree(&r2)
r1.Op = OINDREG r1.Op = OINDREG
r1.Type = res.Type.Type r1.Type = res.Type.Elem()
cgen_wb(n2, &r1, needwritebarrier(&r1, n2)) cgen_wb(n2, &r1, needwritebarrier(&r1, n2))
Regfree(&r1) Regfree(&r1)
i++ i++
@ -3025,7 +3025,7 @@ func cgen_slice(n, res *Node, wb bool) {
return return
} }
if n.Op == OSLICEARR || n.Op == OSLICE3ARR { if n.Op == OSLICEARR || n.Op == OSLICE3ARR {
Nodconst(&xlen, indexRegType, n.Left.Type.Type.Bound) Nodconst(&xlen, indexRegType, n.Left.Type.Elem().Bound)
return return
} }
if n.Op == OSLICESTR && Isconst(n.Left, CTSTR) { if n.Op == OSLICESTR && Isconst(n.Left, CTSTR) {
@ -3183,7 +3183,7 @@ func cgen_slice(n, res *Node, wb bool) {
// The func obvious below checks for out-of-order constant indexes. // The func obvious below checks for out-of-order constant indexes.
var bound int64 = -1 var bound int64 = -1
if n.Op == OSLICEARR || n.Op == OSLICE3ARR { if n.Op == OSLICEARR || n.Op == OSLICE3ARR {
bound = n.Left.Type.Type.Bound bound = n.Left.Type.Elem().Bound
} else if n.Op == OSLICESTR && Isconst(n.Left, CTSTR) { } else if n.Op == OSLICESTR && Isconst(n.Left, CTSTR) {
bound = int64(len(n.Left.Val().U.(string))) bound = int64(len(n.Left.Val().U.(string)))
} }
@ -3467,7 +3467,17 @@ func cgen_slice(n, res *Node, wb bool) {
Cgenr(n.Left, &xbase, nil) Cgenr(n.Left, &xbase, nil)
Cgen_checknil(&xbase) Cgen_checknil(&xbase)
} else { } else {
regalloc(&xbase, Ptrto(res.Type.Type), nil) var ptr *Type
if n.Op == OSLICESTR {
// Yikes! Ptrto(nil)?!
// Prior to CL 21331, that's what this code did implicitly.
// Now it does it explicitly, to safely preserve old behavior.
// This will all be replaced by SSA anyway.
ptr = Ptrto(nil)
} else {
ptr = Ptrto(n.Type.Elem())
}
regalloc(&xbase, ptr, nil)
x.Type = xbase.Type x.Type = xbase.Type
Thearch.Gmove(&x, &xbase) Thearch.Gmove(&x, &xbase)
Regfree(&x) Regfree(&x)
@ -3490,7 +3500,7 @@ func cgen_slice(n, res *Node, wb bool) {
if n.Op == OSLICESTR { if n.Op == OSLICESTR {
w = 1 // res is string, elem size is 1 (byte) w = 1 // res is string, elem size is 1 (byte)
} else { } else {
w = res.Type.Type.Width // res is []T, elem size is T.width w = res.Type.Elem().Width // res is []T, elem size is T.width
} }
if Isconst(&i, CTINT) { if Isconst(&i, CTINT) {
ginscon(Thearch.Optoas(OADD, xbase.Type), i.Val().U.(*Mpint).Int64()*w, &xbase) ginscon(Thearch.Optoas(OADD, xbase.Type), i.Val().U.(*Mpint).Int64()*w, &xbase)

View File

@ -490,7 +490,7 @@ func makepartialcall(fn *Node, t0 *Type, meth *Sym) *Node {
} }
basetype := rcvrtype basetype := rcvrtype
if Isptr[rcvrtype.Etype] { if Isptr[rcvrtype.Etype] {
basetype = basetype.Type basetype = basetype.Elem()
} }
if basetype.Etype != TINTER && basetype.Sym == nil { if basetype.Etype != TINTER && basetype.Sym == nil {
Fatalf("missing base type for %v", rcvrtype) Fatalf("missing base type for %v", rcvrtype)

View File

@ -1684,7 +1684,7 @@ func isgoconst(n *Node) bool {
t := l.Type t := l.Type
if t != nil && Isptr[t.Etype] { if t != nil && Isptr[t.Etype] {
t = t.Type t = t.Elem()
} }
if Isfixedarray(t) && !hascallchan(l) { if Isfixedarray(t) && !hascallchan(l) {
return true return true

View File

@ -716,7 +716,7 @@ func checkembeddedtype(t *Type) {
} }
if t.Sym == nil && Isptr[t.Etype] { if t.Sym == nil && Isptr[t.Etype] {
t = t.Type t = t.Elem()
if t.Etype == TINTER { if t.Etype == TINTER {
Yyerror("embedded type cannot be a pointer to interface") Yyerror("embedded type cannot be a pointer to interface")
} }
@ -1020,7 +1020,7 @@ func isifacemethod(f *Type) bool {
if !Isptr[t.Etype] { if !Isptr[t.Etype] {
return false return false
} }
t = t.Type t = t.Elem()
if t.Sym != nil || t.Etype != TSTRUCT || t.NumFields() != 0 { if t.Sym != nil || t.Etype != TSTRUCT || t.NumFields() != 0 {
return false return false
} }
@ -1076,7 +1076,7 @@ func methodsym(nsym *Sym, t0 *Type, iface int) *Sym {
} }
s = t.Sym s = t.Sym
if s == nil && Isptr[t.Etype] { if s == nil && Isptr[t.Etype] {
t = t.Type t = t.Elem()
if t == nil { if t == nil {
goto bad goto bad
} }
@ -1198,7 +1198,7 @@ func addmethod(msym *Sym, t *Type, tpkg *Pkg, local, nointerface bool) {
return return
} }
t = t.Type t = t.Elem()
} }
if t.Broke { // rely on typecheck having complained before if t.Broke { // rely on typecheck having complained before

View File

@ -640,7 +640,7 @@ func esc(e *EscState, n *Node, up *Node) {
// "Big" conditions that were scattered around in walk have been gathered here // "Big" conditions that were scattered around in walk have been gathered here
if n.Esc != EscHeap && n.Type != nil && if n.Esc != EscHeap && n.Type != nil &&
(n.Type.Width > MaxStackVarSize || (n.Type.Width > MaxStackVarSize ||
n.Op == ONEW && n.Type.Type.Width >= 1<<16 || n.Op == ONEW && n.Type.Elem().Width >= 1<<16 ||
n.Op == OMAKESLICE && !isSmallMakeSlice(n)) { n.Op == OMAKESLICE && !isSmallMakeSlice(n)) {
if Debug['m'] > 2 { if Debug['m'] > 2 {
Warnl(n.Lineno, "%v is too large for stack", n) Warnl(n.Lineno, "%v is too large for stack", n)
@ -697,7 +697,7 @@ func esc(e *EscState, n *Node, up *Node) {
// it is also a dereference, because it is implicitly // it is also a dereference, because it is implicitly
// dereferenced (see #12588) // dereferenced (see #12588)
if Isfixedarray(n.Type) && if Isfixedarray(n.Type) &&
!(Isptr[n.Right.Type.Etype] && Eqtype(n.Right.Type.Type, n.Type)) { !(Isptr[n.Right.Type.Etype] && Eqtype(n.Right.Type.Elem(), n.Type)) {
escassignNilWhy(e, n.List.Second(), n.Right, "range") escassignNilWhy(e, n.List.Second(), n.Right, "range")
} else { } else {
escassignDereference(e, n.List.Second(), n.Right, e.stepAssign(nil, n.List.Second(), n.Right, "range-deref")) escassignDereference(e, n.List.Second(), n.Right, e.stepAssign(nil, n.List.Second(), n.Right, "range-deref"))
@ -1341,7 +1341,7 @@ func (e *EscState) addDereference(n *Node) *Node {
// This should model our own sloppy use of OIND to encode // This should model our own sloppy use of OIND to encode
// decreasing levels of indirection; i.e., "indirecting" an array // decreasing levels of indirection; i.e., "indirecting" an array
// might yield the type of an element. To be enhanced... // might yield the type of an element. To be enhanced...
t = t.Type t = t.Elem()
} }
ind.Type = t ind.Type = t
return ind return ind
@ -1493,7 +1493,7 @@ func esccall(e *EscState, n *Node, up *Node) {
if n2.Isddd && !n.Isddd { if n2.Isddd && !n.Isddd {
// Introduce ODDDARG node to represent ... allocation. // Introduce ODDDARG node to represent ... allocation.
src = Nod(ODDDARG, nil, nil) src = Nod(ODDDARG, nil, nil)
arr := typArray(n2.Type.Type, int64(len(lls))) arr := typArray(n2.Type.Elem(), int64(len(lls)))
src.Type = Ptrto(arr) // make pointer so it will be tracked src.Type = Ptrto(arr) // make pointer so it will be tracked
src.Lineno = n.Lineno src.Lineno = n.Lineno
e.track(src) e.track(src)
@ -1555,7 +1555,7 @@ func esccall(e *EscState, n *Node, up *Node) {
// Introduce ODDDARG node to represent ... allocation. // Introduce ODDDARG node to represent ... allocation.
src = Nod(ODDDARG, nil, nil) src = Nod(ODDDARG, nil, nil)
src.Lineno = n.Lineno src.Lineno = n.Lineno
arr := typArray(t.Type.Type, int64(len(lls)-i)) arr := typArray(t.Type.Elem(), int64(len(lls)-i))
src.Type = Ptrto(arr) // make pointer so it will be tracked src.Type = Ptrto(arr) // make pointer so it will be tracked
e.track(src) e.track(src)
n.Right = src n.Right = src

View File

@ -150,7 +150,7 @@ func reexportdep(n *Node) {
if t != Types[t.Etype] && t != idealbool && t != idealstring { if t != Types[t.Etype] && t != idealbool && t != idealstring {
if Isptr[t.Etype] { if Isptr[t.Etype] {
t = t.Type t = t.Elem()
} }
if t != nil && t.Sym != nil && t.Sym.Def != nil && !exportedsym(t.Sym) { if t != nil && t.Sym != nil && t.Sym.Def != nil && !exportedsym(t.Sym) {
if Debug['E'] != 0 { if Debug['E'] != 0 {
@ -164,7 +164,7 @@ func reexportdep(n *Node) {
t := n.Type t := n.Type
if t != Types[n.Type.Etype] && t != idealbool && t != idealstring { if t != Types[n.Type.Etype] && t != idealbool && t != idealstring {
if Isptr[t.Etype] { if Isptr[t.Etype] {
t = t.Type t = t.Elem()
} }
if t != nil && t.Sym != nil && t.Sym.Def != nil && !exportedsym(t.Sym) { if t != nil && t.Sym != nil && t.Sym.Def != nil && !exportedsym(t.Sym) {
if Debug['E'] != 0 { if Debug['E'] != 0 {
@ -205,7 +205,7 @@ func reexportdep(n *Node) {
switch t.Etype { switch t.Etype {
case TARRAY, TCHAN, TPTR32, TPTR64: case TARRAY, TCHAN, TPTR32, TPTR64:
if t.Sym == nil { if t.Sym == nil {
t = t.Type t = t.Elem()
} }
} }
if t != nil && t.Sym != nil && t.Sym.Def != nil && !exportedsym(t.Sym) { if t != nil && t.Sym != nil && t.Sym.Def != nil && !exportedsym(t.Sym) {
@ -304,7 +304,7 @@ func dumpexporttype(t *Type) {
dumpexporttype(t.Val()) dumpexporttype(t.Val())
dumpexporttype(t.Key()) dumpexporttype(t.Key())
case TARRAY, TCHAN, TPTR32, TPTR64: case TARRAY, TCHAN, TPTR32, TPTR64:
dumpexporttype(t.Type) dumpexporttype(t.Elem())
} }
if t.Sym == nil { if t.Sym == nil {

View File

@ -581,32 +581,32 @@ func typefmt(t *Type, flag FmtFlag) string {
switch t.Etype { switch t.Etype {
case TPTR32, TPTR64: case TPTR32, TPTR64:
if fmtmode == FTypeId && (flag&FmtShort != 0) { if fmtmode == FTypeId && (flag&FmtShort != 0) {
return "*" + Tconv(t.Type, FmtShort) return "*" + Tconv(t.Elem(), FmtShort)
} }
return "*" + t.Type.String() return "*" + t.Elem().String()
case TARRAY: case TARRAY:
if t.IsArray() { if t.IsArray() {
return fmt.Sprintf("[%d]%v", t.Bound, t.Type) return fmt.Sprintf("[%d]%v", t.Bound, t.Elem())
} }
if t.isDDDArray() { if t.isDDDArray() {
return "[...]" + t.Type.String() return "[...]" + t.Elem().String()
} }
return "[]" + t.Type.String() return "[]" + t.Elem().String()
case TCHAN: case TCHAN:
switch t.Chan { switch t.Chan {
case Crecv: case Crecv:
return "<-chan " + t.Type.String() return "<-chan " + t.Elem().String()
case Csend: case Csend:
return "chan<- " + t.Type.String() return "chan<- " + t.Elem().String()
} }
if t.Type != nil && t.Type.Etype == TCHAN && t.Type.Sym == nil && t.Type.Chan == Crecv { if t.Elem() != nil && t.Elem().Etype == TCHAN && t.Elem().Sym == nil && t.Elem().Chan == Crecv {
return "chan (" + t.Type.String() + ")" return "chan (" + t.Elem().String() + ")"
} }
return "chan " + t.Type.String() return "chan " + t.Elem().String()
case TMAP: case TMAP:
return "map[" + t.Key().String() + "]" + t.Val().String() return "map[" + t.Key().String() + "]" + t.Val().String()
@ -736,7 +736,7 @@ func typefmt(t *Type, flag FmtFlag) string {
} }
// Don't know how to handle - fall back to detailed prints. // Don't know how to handle - fall back to detailed prints.
return fmt.Sprintf("%v <%v> %v", Econv(t.Etype), t.Sym, t.Type) return fmt.Sprintf("%v <%v> %v", Econv(t.Etype), t.Sym, t.Elem())
} }
// Statements which may be rendered with a simplestmt as init. // Statements which may be rendered with a simplestmt as init.
@ -1185,7 +1185,7 @@ func exprfmt(n *Node, prec int) string {
if fmtmode == FErr { if fmtmode == FErr {
if n.Right != nil && n.Right.Type != nil && !n.Implicit { if n.Right != nil && n.Right.Type != nil && !n.Implicit {
if ptrlit { if ptrlit {
return fmt.Sprintf("&%v literal", n.Right.Type.Type) return fmt.Sprintf("&%v literal", n.Right.Type.Elem())
} else { } else {
return fmt.Sprintf("%v literal", n.Right.Type) return fmt.Sprintf("%v literal", n.Right.Type)
} }
@ -1196,7 +1196,7 @@ func exprfmt(n *Node, prec int) string {
if fmtmode == FExp && ptrlit { if fmtmode == FExp && ptrlit {
// typecheck has overwritten OIND by OTYPE with pointer type. // typecheck has overwritten OIND by OTYPE with pointer type.
return fmt.Sprintf("(&%v{ %v })", n.Right.Type.Type, Hconv(n.List, FmtComma)) return fmt.Sprintf("(&%v{ %v })", n.Right.Type.Elem(), Hconv(n.List, FmtComma))
} }
return fmt.Sprintf("(%v{ %v })", n.Right, Hconv(n.List, FmtComma)) return fmt.Sprintf("(%v{ %v })", n.Right, Hconv(n.List, FmtComma))
@ -1652,7 +1652,7 @@ func Fldconv(f *Field, flag FmtFlag) string {
var typ string var typ string
if f.Isddd { if f.Isddd {
typ = "..." + Tconv(f.Type.Type, 0) typ = "..." + Tconv(f.Type.Elem(), 0)
} else { } else {
typ = Tconv(f.Type, 0) typ = Tconv(f.Type, 0)
} }

View File

@ -1205,35 +1205,24 @@ func visitComponents(t *Type, startOffset int64, f func(elem *Type, elemOffset i
case TARRAY: case TARRAY:
if Isslice(t) { if Isslice(t) {
return f(Ptrto(t.Type), startOffset+int64(Array_array)) && return f(Ptrto(t.Elem()), startOffset+int64(Array_array)) &&
f(Types[Simtype[TUINT]], startOffset+int64(Array_nel)) && f(Types[Simtype[TUINT]], startOffset+int64(Array_nel)) &&
f(Types[Simtype[TUINT]], startOffset+int64(Array_cap)) f(Types[Simtype[TUINT]], startOffset+int64(Array_cap))
} }
// Short-circuit [1e6]struct{}. // Short-circuit [1e6]struct{}.
if t.Type.Width == 0 { if t.Elem().Width == 0 {
return true return true
} }
for i := int64(0); i < t.Bound; i++ { for i := int64(0); i < t.Bound; i++ {
if !visitComponents(t.Type, startOffset+i*t.Type.Width, f) { if !visitComponents(t.Elem(), startOffset+i*t.Elem().Width, f) {
return false return false
} }
} }
return true return true
case TSTRUCT: case TSTRUCT:
if t.Type != nil && t.Type.Width != 0 {
// NOTE(rsc): If this happens, the right thing to do is to say
// startOffset -= t.Type.Width
// but I want to see if it does.
// The old version of componentgen handled this,
// in code introduced in CL 6932045 to fix issue #4518.
// But the test case in issue 4518 does not trigger this anymore,
// so maybe this complication is no longer needed.
Fatalf("struct not at offset 0")
}
for _, field := range t.Fields().Slice() { for _, field := range t.Fields().Slice() {
if !visitComponents(field.Type, startOffset+field.Offset, f) { if !visitComponents(field.Type, startOffset+field.Offset, f) {
return false return false

View File

@ -39,7 +39,7 @@ func fnpkg(fn *Node) *Pkg {
rcvr := fn.Type.Recv().Type rcvr := fn.Type.Recv().Type
if Isptr[rcvr.Etype] { if Isptr[rcvr.Etype] {
rcvr = rcvr.Type rcvr = rcvr.Elem()
} }
if rcvr.Sym == nil { if rcvr.Sym == nil {
Fatalf("receiver with no sym: [%v] %v (%v)", fn.Sym, Nconv(fn, FmtLong), rcvr) Fatalf("receiver with no sym: [%v] %v (%v)", fn.Sym, Nconv(fn, FmtLong), rcvr)
@ -747,7 +747,7 @@ func mkinlcall1(n *Node, fn *Node, isddd bool) *Node {
as.Right = nodnil() as.Right = nodnil()
as.Right.Type = varargtype as.Right.Type = varargtype
} else { } else {
vararrtype := typArray(varargtype.Type, int64(varargcount)) vararrtype := typArray(varargtype.Elem(), int64(varargcount))
as.Right = Nod(OCOMPLIT, nil, typenod(vararrtype)) as.Right = Nod(OCOMPLIT, nil, typenod(vararrtype))
as.Right.List.Set(varargs) as.Right.List.Set(varargs)
as.Right = Nod(OSLICE, as.Right, Nod(OKEY, nil, nil)) as.Right = Nod(OSLICE, as.Right, Nod(OKEY, nil, nil))
@ -866,7 +866,7 @@ func retvar(t *Field, i int) *Node {
// when they come from a multiple return call. // when they come from a multiple return call.
func argvar(t *Type, i int) *Node { func argvar(t *Type, i int) *Node {
n := newname(LookupN("~arg", i)) n := newname(LookupN("~arg", i))
n.Type = t.Type n.Type = t.Elem()
n.Class = PAUTO n.Class = PAUTO
n.Used = true n.Used = true
n.Name.Curfn = Curfn // the calling function, not the called one n.Name.Curfn = Curfn // the calling function, not the called one

View File

@ -591,7 +591,7 @@ func orderstmt(n *Node, order *Order) {
orderexprlist(n.List, order) orderexprlist(n.List, order)
n.Rlist.First().Left = orderexpr(n.Rlist.First().Left, order, nil) // arg to recv n.Rlist.First().Left = orderexpr(n.Rlist.First().Left, order, nil) // arg to recv
ch := n.Rlist.First().Left.Type ch := n.Rlist.First().Left.Type
tmp1 := ordertemp(ch.Type, order, haspointers(ch.Type)) tmp1 := ordertemp(ch.Elem(), order, haspointers(ch.Elem()))
var tmp2 *Node var tmp2 *Node
if !isblank(n.List.Second()) { if !isblank(n.List.Second()) {
tmp2 = ordertemp(n.List.Second().Type, order, false) tmp2 = ordertemp(n.List.Second().Type, order, false)
@ -861,7 +861,7 @@ func orderstmt(n *Node, order *Order) {
n2.Ninit.Append(tmp2) n2.Ninit.Append(tmp2)
} }
r.Left = ordertemp(r.Right.Left.Type.Type, order, haspointers(r.Right.Left.Type.Type)) r.Left = ordertemp(r.Right.Left.Type.Elem(), order, haspointers(r.Right.Left.Type.Elem()))
tmp2 = Nod(OAS, tmp1, r.Left) tmp2 = Nod(OAS, tmp1, r.Left)
tmp2 = typecheck(tmp2, Etop) tmp2 = typecheck(tmp2, Etop)
n2.Ninit.Append(tmp2) n2.Ninit.Append(tmp2)
@ -1165,7 +1165,7 @@ func orderexpr(n *Node, order *Order, lhs *Node) *Node {
// Allocate a temporary that will be cleaned up when this statement // Allocate a temporary that will be cleaned up when this statement
// completes. We could be more aggressive and try to arrange for it // completes. We could be more aggressive and try to arrange for it
// to be cleaned up when the call completes. // to be cleaned up when the call completes.
prealloc[n] = ordertemp(n.Type.Type, order, false) prealloc[n] = ordertemp(n.Type.Elem(), order, false)
} }
case ODOTTYPE, ODOTTYPE2: case ODOTTYPE, ODOTTYPE2:

View File

@ -3154,7 +3154,7 @@ func (p *parser) hidden_structdcl() *Node {
} else { } else {
s := s2.Sym s := s2.Sym
if s == nil && Isptr[s2.Etype] { if s == nil && Isptr[s2.Etype] {
s = s2.Type.Sym s = s2.Elem().Sym
} }
pkg := importpkg pkg := importpkg
if s1 != nil { if s1 != nil {

View File

@ -932,7 +932,7 @@ func onebitwalktype1(t *Type, xoffset *int64, bv Bvec) {
*xoffset += t.Width *xoffset += t.Width
} else { } else {
for i := int64(0); i < t.Bound; i++ { for i := int64(0); i < t.Bound; i++ {
onebitwalktype1(t.Type, xoffset, bv) onebitwalktype1(t.Elem(), xoffset, bv)
} }
} }

View File

@ -38,8 +38,8 @@ func typecheckrange(n *Node) {
} }
} }
if Isptr[t.Etype] && Isfixedarray(t.Type) { if Isptr[t.Etype] && Isfixedarray(t.Elem()) {
t = t.Type t = t.Elem()
} }
n.Type = t n.Type = t
@ -51,7 +51,7 @@ func typecheckrange(n *Node) {
case TARRAY: case TARRAY:
t1 = Types[TINT] t1 = Types[TINT]
t2 = t.Type t2 = t.Elem()
case TMAP: case TMAP:
t1 = t.Key() t1 = t.Key()
@ -63,7 +63,7 @@ func typecheckrange(n *Node) {
goto out goto out
} }
t1 = t.Type t1 = t.Elem()
t2 = nil t2 = nil
if n.List.Len() == 2 { if n.List.Len() == 2 {
toomany = 1 toomany = 1
@ -180,7 +180,7 @@ func walkrange(n *Node) {
init = append(init, Nod(OAS, hv1, nil)) init = append(init, Nod(OAS, hv1, nil))
init = append(init, Nod(OAS, hn, Nod(OLEN, ha, nil))) init = append(init, Nod(OAS, hn, Nod(OLEN, ha, nil)))
if v2 != nil { if v2 != nil {
hp = temp(Ptrto(n.Type.Type)) hp = temp(Ptrto(n.Type.Elem()))
tmp := Nod(OINDEX, ha, Nodintconst(0)) tmp := Nod(OINDEX, ha, Nodintconst(0))
tmp.Bounded = true tmp.Bounded = true
init = append(init, Nod(OAS, hp, Nod(OADDR, tmp, nil))) init = append(init, Nod(OAS, hp, Nod(OADDR, tmp, nil)))
@ -206,7 +206,7 @@ func walkrange(n *Node) {
// Advancing during the increment ensures that the pointer p only points // Advancing during the increment ensures that the pointer p only points
// pass the end of the array during the final "p++; i++; if(i >= len(x)) break;", // pass the end of the array during the final "p++; i++; if(i >= len(x)) break;",
// after which p is dead, so it cannot confuse the collector. // after which p is dead, so it cannot confuse the collector.
tmp := Nod(OADD, hp, Nodintconst(t.Type.Width)) tmp := Nod(OADD, hp, Nodintconst(t.Elem().Width))
tmp.Type = hp.Type tmp.Type = hp.Type
tmp.Typecheck = 1 tmp.Typecheck = 1
@ -260,9 +260,9 @@ func walkrange(n *Node) {
n.Left = nil n.Left = nil
hv1 := temp(t.Type) hv1 := temp(t.Elem())
hv1.Typecheck = 1 hv1.Typecheck = 1
if haspointers(t.Type) { if haspointers(t.Elem()) {
init = append(init, Nod(OAS, hv1, nil)) init = append(init, Nod(OAS, hv1, nil))
} }
hb := temp(Types[TBOOL]) hb := temp(Types[TBOOL])
@ -353,7 +353,7 @@ func memclrrange(n, v1, v2, a *Node) bool {
if !samesafeexpr(stmt.Left.Left, a) || !samesafeexpr(stmt.Left.Right, v1) { if !samesafeexpr(stmt.Left.Left, a) || !samesafeexpr(stmt.Left.Right, v1) {
return false return false
} }
elemsize := n.Type.Type.Width elemsize := n.Type.Elem().Width
if elemsize <= 0 || !iszero(stmt.Right) { if elemsize <= 0 || !iszero(stmt.Right) {
return false return false
} }

View File

@ -306,7 +306,7 @@ func methods(t *Type) []*Sig {
// method does not apply. // method does not apply.
this := f.Type.Recv().Type this := f.Type.Recv().Type
if Isptr[this.Etype] && this.Type == t { if Isptr[this.Etype] && this.Elem() == t {
continue continue
} }
if Isptr[this.Etype] && !Isptr[t.Etype] && f.Embedded != 2 && !isifacemethod(f.Type) { if Isptr[this.Etype] && !Isptr[t.Etype] && f.Embedded != 2 && !isifacemethod(f.Type) {
@ -582,8 +582,13 @@ func dextratype(s *Sym, ot int, t *Type, dataAdd int) int {
func typePkg(t *Type) *Pkg { func typePkg(t *Type) *Pkg {
tsym := t.Sym tsym := t.Sym
if tsym == nil && t.Type != nil { if tsym == nil {
tsym = t.Type.Sym switch t.Etype {
case TARRAY, TPTR32, TPTR64, TCHAN:
if t.Elem() != nil {
tsym = t.Elem().Sym
}
}
} }
if tsym != nil && t != Types[t.Etype] && t != errortype { if tsym != nil && t != Types[t.Etype] && t != errortype {
return tsym.Pkg return tsym.Pkg
@ -684,7 +689,7 @@ func haspointers(t *Type) bool {
break break
} }
ret = haspointers(t.Type) ret = haspointers(t.Elem())
case TSTRUCT: case TSTRUCT:
ret = false ret = false
@ -743,7 +748,7 @@ func typeptrdata(t *Type) int64 {
return int64(Widthptr) return int64(Widthptr)
} }
// haspointers already eliminated t.Bound == 0. // haspointers already eliminated t.Bound == 0.
return (t.Bound-1)*t.Type.Width + typeptrdata(t.Type) return (t.Bound-1)*t.Elem().Width + typeptrdata(t.Elem())
case TSTRUCT: case TSTRUCT:
// Find the last field that has pointers. // Find the last field that has pointers.
@ -913,7 +918,7 @@ func typesymprefix(prefix string, t *Type) *Sym {
} }
func typenamesym(t *Type) *Sym { func typenamesym(t *Type) *Sym {
if t == nil || (Isptr[t.Etype] && t.Type == nil) || isideal(t) { if t == nil || (Isptr[t.Etype] && t.Elem() == nil) || isideal(t) {
Fatalf("typename %v", t) Fatalf("typename %v", t)
} }
s := typesym(t) s := typesym(t)
@ -941,7 +946,7 @@ func typename(t *Type) *Node {
} }
func itabname(t, itype *Type) *Node { func itabname(t, itype *Type) *Node {
if t == nil || (Isptr[t.Etype] && t.Type == nil) || isideal(t) { if t == nil || (Isptr[t.Etype] && t.Elem() == nil) || isideal(t) {
Fatalf("itabname %v", t) Fatalf("itabname %v", t)
} }
s := Pkglookup(Tconv(t, FmtLeft)+","+Tconv(itype, FmtLeft), itabpkg) s := Pkglookup(Tconv(t, FmtLeft)+","+Tconv(itype, FmtLeft), itabpkg)
@ -997,7 +1002,7 @@ func isreflexive(t *Type) bool {
if Isslice(t) { if Isslice(t) {
Fatalf("slice can't be a map key: %v", t) Fatalf("slice can't be a map key: %v", t)
} }
return isreflexive(t.Type) return isreflexive(t.Elem())
case TSTRUCT: case TSTRUCT:
for _, t1 := range t.Fields().Slice() { for _, t1 := range t.Fields().Slice() {
@ -1047,7 +1052,7 @@ func needkeyupdate(t *Type) bool {
if Isslice(t) { if Isslice(t) {
Fatalf("slice can't be a map key: %v", t) Fatalf("slice can't be a map key: %v", t)
} }
return needkeyupdate(t.Type) return needkeyupdate(t.Elem())
case TSTRUCT: case TSTRUCT:
for _, t1 := range t.Fields().Slice() { for _, t1 := range t.Fields().Slice() {
@ -1086,8 +1091,8 @@ func dtypesym(t *Type) *Sym {
// emit the type structures for int, float, etc. // emit the type structures for int, float, etc.
tbase := t tbase := t
if Isptr[t.Etype] && t.Sym == nil && t.Type.Sym != nil { if Isptr[t.Etype] && t.Sym == nil && t.Elem().Sym != nil {
tbase = t.Type tbase = t.Elem()
} }
dupok := 0 dupok := 0
if tbase.Sym == nil { if tbase.Sym == nil {
@ -1116,8 +1121,8 @@ ok:
case TARRAY: case TARRAY:
if t.IsArray() { if t.IsArray() {
// ../../../../runtime/type.go:/arrayType // ../../../../runtime/type.go:/arrayType
s1 := dtypesym(t.Type) s1 := dtypesym(t.Elem())
t2 := typSlice(t.Type) t2 := typSlice(t.Elem())
s2 := dtypesym(t2) s2 := dtypesym(t2)
ot = dcommontype(s, ot, t) ot = dcommontype(s, ot, t)
ot = dsymptr(s, ot, s1, 0) ot = dsymptr(s, ot, s1, 0)
@ -1125,7 +1130,7 @@ ok:
ot = duintptr(s, ot, uint64(t.Bound)) ot = duintptr(s, ot, uint64(t.Bound))
} else { } else {
// ../../../../runtime/type.go:/sliceType // ../../../../runtime/type.go:/sliceType
s1 := dtypesym(t.Type) s1 := dtypesym(t.Elem())
ot = dcommontype(s, ot, t) ot = dcommontype(s, ot, t)
ot = dsymptr(s, ot, s1, 0) ot = dsymptr(s, ot, s1, 0)
@ -1134,7 +1139,7 @@ ok:
// ../../../../runtime/type.go:/chanType // ../../../../runtime/type.go:/chanType
case TCHAN: case TCHAN:
s1 := dtypesym(t.Type) s1 := dtypesym(t.Elem())
ot = dcommontype(s, ot, t) ot = dcommontype(s, ot, t)
ot = dsymptr(s, ot, s1, 0) ot = dsymptr(s, ot, s1, 0)
@ -1246,7 +1251,7 @@ ok:
ot = dextratype(s, ot, t, 0) ot = dextratype(s, ot, t, 0)
case TPTR32, TPTR64: case TPTR32, TPTR64:
if t.Type.Etype == TANY { if t.Elem().Etype == TANY {
// ../../../../runtime/type.go:/UnsafePointerType // ../../../../runtime/type.go:/UnsafePointerType
ot = dcommontype(s, ot, t) ot = dcommontype(s, ot, t)
ot = dextratype(s, ot, t, 0) ot = dextratype(s, ot, t, 0)
@ -1255,7 +1260,7 @@ ok:
} }
// ../../../../runtime/type.go:/ptrType // ../../../../runtime/type.go:/ptrType
s1 := dtypesym(t.Type) s1 := dtypesym(t.Elem())
ot = dcommontype(s, ot, t) ot = dcommontype(s, ot, t)
ot = dsymptr(s, ot, s1, 0) ot = dsymptr(s, ot, s1, 0)
@ -1639,10 +1644,10 @@ func (p *GCProg) emit(t *Type, offset int64) {
// Flatten array-of-array-of-array to just a big array by multiplying counts. // Flatten array-of-array-of-array to just a big array by multiplying counts.
count := t.Bound count := t.Bound
elem := t.Type elem := t.Elem()
for Isfixedarray(elem) { for Isfixedarray(elem) {
count *= elem.Bound count *= elem.Bound
elem = elem.Type elem = elem.Elem()
} }
if !p.w.ShouldRepeat(elem.Width/int64(Widthptr), count) { if !p.w.ShouldRepeat(elem.Width/int64(Widthptr), count) {

View File

@ -434,7 +434,7 @@ func staticassign(l *Node, r *Node, out *[]*Node) bool {
if Isslice(r.Type) { if Isslice(r.Type) {
// Init slice. // Init slice.
bound := r.Right.Val().U.(*Mpint).Int64() bound := r.Right.Val().U.(*Mpint).Int64()
ta := typArray(r.Type.Type, bound) ta := typArray(r.Type.Elem(), bound)
a := staticname(ta, 1) a := staticname(ta, 1)
inittemps[r] = a inittemps[r] = a
n := *l n := *l
@ -1233,7 +1233,7 @@ func initplan(n *Node) {
if a.Op != OKEY || !Smallintconst(a.Left) { if a.Op != OKEY || !Smallintconst(a.Left) {
Fatalf("initplan arraylit") Fatalf("initplan arraylit")
} }
addvalue(p, n.Type.Type.Width*a.Left.Val().U.(*Mpint).Int64(), a.Right) addvalue(p, n.Type.Elem().Width*a.Left.Val().U.(*Mpint).Int64(), a.Right)
} }
case OSTRUCTLIT: case OSTRUCTLIT:

View File

@ -1950,11 +1950,11 @@ func (s *state) expr(n *Node) *ssa.Value {
return s.newValue2(ssa.OpLoad, Types[TUINT8], ptr, s.mem()) return s.newValue2(ssa.OpLoad, Types[TUINT8], ptr, s.mem())
case n.Left.Type.IsSlice(): case n.Left.Type.IsSlice():
p := s.addr(n, false) p := s.addr(n, false)
return s.newValue2(ssa.OpLoad, n.Left.Type.Type, p, s.mem()) return s.newValue2(ssa.OpLoad, n.Left.Type.Elem(), p, s.mem())
case n.Left.Type.IsArray(): case n.Left.Type.IsArray():
// TODO: fix when we can SSA arrays of length 1. // TODO: fix when we can SSA arrays of length 1.
p := s.addr(n, false) p := s.addr(n, false)
return s.newValue2(ssa.OpLoad, n.Left.Type.Type, p, s.mem()) return s.newValue2(ssa.OpLoad, n.Left.Type.Elem(), p, s.mem())
default: default:
s.Fatalf("bad type for index %v", n.Left.Type) s.Fatalf("bad type for index %v", n.Left.Type)
return nil return nil
@ -2077,7 +2077,7 @@ func (s *state) expr(n *Node) *ssa.Value {
// *(ptr+len+2) = e3 // *(ptr+len+2) = e3
// makeslice(ptr,newlen,cap) // makeslice(ptr,newlen,cap)
et := n.Type.Type et := n.Type.Elem()
pt := Ptrto(et) pt := Ptrto(et)
// Evaluate slice // Evaluate slice
@ -2672,7 +2672,7 @@ func (s *state) addr(n *Node, bounded bool) *ssa.Value {
if !n.Bounded { if !n.Bounded {
s.boundsCheck(i, len) s.boundsCheck(i, len)
} }
return s.newValue2(ssa.OpPtrIndex, Ptrto(n.Left.Type.Type), a, i) return s.newValue2(ssa.OpPtrIndex, Ptrto(n.Left.Type.Elem()), a, i)
} }
case OIND: case OIND:
p := s.expr(n.Left) p := s.expr(n.Left)
@ -3138,7 +3138,7 @@ func (s *state) slice(t *Type, v, i, j, k *ssa.Value) (p, l, c *ssa.Value) {
zero := s.constInt(Types[TINT], 0) zero := s.constInt(Types[TINT], 0)
switch { switch {
case t.IsSlice(): case t.IsSlice():
elemtype = t.Type elemtype = t.Elem()
ptrtype = Ptrto(elemtype) ptrtype = Ptrto(elemtype)
ptr = s.newValue1(ssa.OpSlicePtr, ptrtype, v) ptr = s.newValue1(ssa.OpSlicePtr, ptrtype, v)
len = s.newValue1(ssa.OpSliceLen, Types[TINT], v) len = s.newValue1(ssa.OpSliceLen, Types[TINT], v)
@ -3150,14 +3150,14 @@ func (s *state) slice(t *Type, v, i, j, k *ssa.Value) (p, l, c *ssa.Value) {
len = s.newValue1(ssa.OpStringLen, Types[TINT], v) len = s.newValue1(ssa.OpStringLen, Types[TINT], v)
cap = len cap = len
case t.IsPtr(): case t.IsPtr():
if !t.Type.IsArray() { if !t.Elem().IsArray() {
s.Fatalf("bad ptr to array in slice %v\n", t) s.Fatalf("bad ptr to array in slice %v\n", t)
} }
elemtype = t.Type.Type elemtype = t.Elem().Elem()
ptrtype = Ptrto(elemtype) ptrtype = Ptrto(elemtype)
s.nilCheck(v) s.nilCheck(v)
ptr = v ptr = v
len = s.constInt(Types[TINT], t.Type.Bound) len = s.constInt(Types[TINT], t.Elem().Bound)
cap = len cap = len
default: default:
s.Fatalf("bad type in slice %v\n", t) s.Fatalf("bad type in slice %v\n", t)

View File

@ -565,7 +565,7 @@ func isptrto(t *Type, et EType) bool {
if !Isptr[t.Etype] { if !Isptr[t.Etype] {
return false return false
} }
t = t.Type t = t.Elem()
if t == nil { if t == nil {
return false return false
} }
@ -633,7 +633,7 @@ func methtype(t *Type, mustname int) *Type {
if t.Sym != nil { if t.Sym != nil {
return nil return nil
} }
t = t.Type t = t.Elem()
if t == nil { if t == nil {
return nil return nil
} }
@ -773,7 +773,7 @@ func eqtype1(t1, t2 *Type, assumedEqual map[typePair]struct{}) bool {
return eqtype1(t1.Val(), t2.Val(), assumedEqual) return eqtype1(t1.Val(), t2.Val(), assumedEqual)
} }
return eqtype1(t1.Type, t2.Type, assumedEqual) return eqtype1(t1.Elem(), t2.Elem(), 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?
@ -886,7 +886,7 @@ func assignop(src *Type, dst *Type, why *string) Op {
// src and dst have identical element types, and // src and dst have identical element types, and
// either src or dst is not a named type. // either src or dst is not a named type.
if src.Etype == TCHAN && src.Chan == Cboth && dst.Etype == TCHAN { if src.Etype == TCHAN && src.Chan == Cboth && dst.Etype == TCHAN {
if Eqtype(src.Type, dst.Type) && (src.Sym == nil || dst.Sym == nil) { if Eqtype(src.Elem(), dst.Elem()) && (src.Sym == nil || dst.Sym == nil) {
return OCONVNOP return OCONVNOP
} }
} }
@ -960,7 +960,7 @@ func convertop(src *Type, dst *Type, why *string) Op {
// 3. src and dst are unnamed pointer types // 3. src and dst are unnamed pointer types
// and their base types have identical underlying types. // and their base types have identical underlying types.
if Isptr[src.Etype] && Isptr[dst.Etype] && src.Sym == nil && dst.Sym == nil { if Isptr[src.Etype] && Isptr[dst.Etype] && src.Sym == nil && dst.Sym == nil {
if Eqtype(src.Type.Orig, dst.Type.Orig) { if Eqtype(src.Elem().Orig, dst.Elem().Orig) {
return OCONVNOP return OCONVNOP
} }
} }
@ -988,10 +988,10 @@ func convertop(src *Type, dst *Type, why *string) Op {
} }
if Isslice(src) && dst.Etype == TSTRING { if Isslice(src) && dst.Etype == TSTRING {
if src.Type.Etype == bytetype.Etype { if src.Elem().Etype == bytetype.Etype {
return OARRAYBYTESTR return OARRAYBYTESTR
} }
if src.Type.Etype == runetype.Etype { if src.Elem().Etype == runetype.Etype {
return OARRAYRUNESTR return OARRAYRUNESTR
} }
} }
@ -999,10 +999,10 @@ func convertop(src *Type, dst *Type, why *string) Op {
// 7. src is a string and dst is []byte or []rune. // 7. src is a string and dst is []byte or []rune.
// String to slice. // String to slice.
if src.Etype == TSTRING && Isslice(dst) { if src.Etype == TSTRING && Isslice(dst) {
if dst.Type.Etype == bytetype.Etype { if dst.Elem().Etype == bytetype.Etype {
return OSTRARRAYBYTE return OSTRARRAYBYTE
} }
if dst.Type.Etype == runetype.Etype { if dst.Elem().Etype == runetype.Etype {
return OSTRARRAYRUNE return OSTRARRAYRUNE
} }
} }
@ -1278,9 +1278,9 @@ func badtype(op Op, tl *Type, tr *Type) {
// common mistake: *struct and *interface. // common mistake: *struct and *interface.
if tl != nil && tr != nil && Isptr[tl.Etype] && Isptr[tr.Etype] { if tl != nil && tr != nil && Isptr[tl.Etype] && Isptr[tr.Etype] {
if tl.Type.Etype == TSTRUCT && tr.Type.Etype == TINTER { if tl.Elem().Etype == TSTRUCT && tr.Elem().Etype == TINTER {
fmt_ += "\n\t(*struct vs *interface)" fmt_ += "\n\t(*struct vs *interface)"
} else if tl.Type.Etype == TINTER && tr.Type.Etype == TSTRUCT { } else if tl.Elem().Etype == TINTER && tr.Elem().Etype == TSTRUCT {
fmt_ += "\n\t(*interface vs *struct)" fmt_ += "\n\t(*interface vs *struct)"
} }
} }
@ -1445,7 +1445,7 @@ var dotlist = make([]Dlist, 10)
func lookdot0(s *Sym, t *Type, save **Field, ignorecase bool) int { func lookdot0(s *Sym, t *Type, save **Field, ignorecase bool) int {
u := t u := t
if Isptr[u.Etype] { if Isptr[u.Etype] {
u = u.Type u = u.Elem()
} }
c := 0 c := 0
@ -1501,7 +1501,7 @@ func adddot1(s *Sym, t *Type, d int, save **Field, ignorecase bool) (c int, more
u = t u = t
if Isptr[u.Etype] { if Isptr[u.Etype] {
u = u.Type u = u.Elem()
} }
if u.Etype != TSTRUCT && u.Etype != TINTER { if u.Etype != TSTRUCT && u.Etype != TINTER {
goto out goto out
@ -1611,7 +1611,7 @@ func expand0(t *Type, followptr bool) {
u := t u := t
if Isptr[u.Etype] { if Isptr[u.Etype] {
followptr = true followptr = true
u = u.Type u = u.Elem()
} }
if u.Etype == TINTER { if u.Etype == TINTER {
@ -1651,7 +1651,7 @@ func expand1(t *Type, top, followptr bool) {
u := t u := t
if Isptr[u.Etype] { if Isptr[u.Etype] {
followptr = true followptr = true
u = u.Type u = u.Elem()
} }
if u.Etype != TSTRUCT && u.Etype != TINTER { if u.Etype != TSTRUCT && u.Etype != TINTER {
@ -1826,7 +1826,7 @@ func genwrapper(rcvr *Type, method *Field, newnam *Sym, iface int) {
methodrcvr := method.Type.Recv().Type methodrcvr := method.Type.Recv().Type
// generate nil pointer check for better error // generate nil pointer check for better error
if Isptr[rcvr.Etype] && rcvr.Type == methodrcvr { if Isptr[rcvr.Etype] && rcvr.Elem() == methodrcvr {
// generating wrapper from *T to T. // generating wrapper from *T to T.
n := Nod(OIF, nil, nil) n := Nod(OIF, nil, nil)
@ -1837,9 +1837,9 @@ func genwrapper(rcvr *Type, method *Field, newnam *Sym, iface int) {
var l []*Node var l []*Node
var v Val var v Val
v.U = rcvr.Type.Sym.Pkg.Name // package name v.U = rcvr.Elem().Sym.Pkg.Name // package name
l = append(l, nodlit(v)) l = append(l, nodlit(v))
v.U = rcvr.Type.Sym.Name // type name v.U = rcvr.Elem().Sym.Name // type name
l = append(l, nodlit(v)) l = append(l, nodlit(v))
v.U = method.Sym.Name v.U = method.Sym.Name
l = append(l, nodlit(v)) // method name l = append(l, nodlit(v)) // method name
@ -1889,7 +1889,7 @@ func genwrapper(rcvr *Type, method *Field, newnam *Sym, iface int) {
testdclstack() testdclstack()
// wrappers where T is anonymous (struct or interface) can be duplicated. // wrappers where T is anonymous (struct or interface) can be duplicated.
if rcvr.Etype == TSTRUCT || rcvr.Etype == TINTER || Isptr[rcvr.Etype] && rcvr.Type.Etype == TSTRUCT { if rcvr.Etype == TSTRUCT || rcvr.Etype == TINTER || Isptr[rcvr.Etype] && rcvr.Elem().Etype == TSTRUCT {
fn.Func.Dupok = true fn.Func.Dupok = true
} }
fn = typecheck(fn, Etop) fn = typecheck(fn, Etop)
@ -2273,7 +2273,7 @@ func isdirectiface(t *Type) bool {
case TARRAY: case TARRAY:
// Array of 1 direct iface type can be direct. // Array of 1 direct iface type can be direct.
return t.Bound == 1 && isdirectiface(t.Type) return t.Bound == 1 && isdirectiface(t.Elem())
case TSTRUCT: case TSTRUCT:
// Struct with 1 field of direct iface type can be direct. // Struct with 1 field of direct iface type can be direct.

View File

@ -503,6 +503,17 @@ func (t *Type) Val() *Type {
return t.Type return t.Type
} }
// Elem returns the type of elements of t.
// Usable with pointers, channels, arrays, and slices.
func (t *Type) Elem() *Type {
switch t.Etype {
case TPTR32, TPTR64, TCHAN, TARRAY:
default:
Fatalf("Type.Elem %s", t.Etype)
}
return t.Type
}
// Wrapped returns the type that pseudo-type t wraps. // Wrapped returns the type that pseudo-type t wraps.
func (t *Type) Wrapped() *Type { func (t *Type) Wrapped() *Type {
switch t.Etype { switch t.Etype {
@ -787,7 +798,7 @@ func (t *Type) cmp(x *Type) ssa.Cmp {
} }
// Common element type comparison for TARRAY, TCHAN, TPTR32, and TPTR64. // Common element type comparison for TARRAY, TCHAN, TPTR32, and TPTR64.
return t.Type.cmp(x.Type) return t.Elem().cmp(x.Elem())
} }
func (t *Type) IsBoolean() bool { func (t *Type) IsBoolean() bool {
@ -864,11 +875,9 @@ func (t *Type) IsInterface() bool {
} }
func (t *Type) ElemType() ssa.Type { func (t *Type) ElemType() ssa.Type {
switch t.Etype { // TODO(josharian): If Type ever moves to a shared
case TARRAY, TPTR32, TPTR64: // internal package, remove this silly wrapper.
return t.Type return t.Elem()
}
panic(fmt.Sprintf("ElemType on invalid type %v", t))
} }
func (t *Type) PtrTo() ssa.Type { func (t *Type) PtrTo() ssa.Type {
return Ptrto(t) return Ptrto(t)

View File

@ -484,7 +484,7 @@ OpSwitch:
} }
ok |= Erv ok |= Erv
n.Type = t.Type n.Type = t.Elem()
break OpSwitch break OpSwitch
// arithmetic exprs // arithmetic exprs
@ -864,8 +864,8 @@ OpSwitch:
break OpSwitch break OpSwitch
} }
if Isptr[t.Etype] && t.Type.Etype != TINTER { if Isptr[t.Etype] && t.Elem().Etype != TINTER {
t = t.Type t = t.Elem()
if t == nil { if t == nil {
n.Type = nil n.Type = nil
return n return n
@ -886,7 +886,7 @@ OpSwitch:
case isnilinter(t): case isnilinter(t):
Yyerror("%v undefined (type %v is interface with no methods)", n, n.Left.Type) Yyerror("%v undefined (type %v is interface with no methods)", n, n.Left.Type)
case Isptr[t.Etype] && Isinter(t.Type): case Isptr[t.Etype] && Isinter(t.Elem()):
// Pointer to interface is almost always a mistake. // Pointer to interface is almost always a mistake.
Yyerror("%v undefined (type %v is pointer to interface, not interface)", n, n.Left.Type) Yyerror("%v undefined (type %v is pointer to interface, not interface)", n, n.Left.Type)
@ -989,7 +989,7 @@ OpSwitch:
if t.Etype == TSTRING { if t.Etype == TSTRING {
n.Type = bytetype n.Type = bytetype
} else { } else {
n.Type = t.Type n.Type = t.Elem()
} }
why := "string" why := "string"
if t.Etype == TARRAY { if t.Etype == TARRAY {
@ -1052,7 +1052,7 @@ OpSwitch:
return n return n
} }
n.Type = t.Type n.Type = t.Elem()
break OpSwitch break OpSwitch
case OSEND: case OSEND:
@ -1079,13 +1079,13 @@ OpSwitch:
return n return n
} }
n.Right = defaultlit(n.Right, t.Type) n.Right = defaultlit(n.Right, t.Elem())
r := n.Right r := n.Right
if r.Type == nil { if r.Type == nil {
n.Type = nil n.Type = nil
return n return n
} }
n.Right = assignconv(r, l.Type.Type, "send") n.Right = assignconv(r, l.Type.Elem(), "send")
// TODO: more aggressive // TODO: more aggressive
n.Etype = 0 n.Etype = 0
@ -1124,9 +1124,9 @@ OpSwitch:
if Istype(t, TSTRING) { if Istype(t, TSTRING) {
n.Type = t n.Type = t
n.Op = OSLICESTR n.Op = OSLICESTR
} else if Isptr[t.Etype] && Isfixedarray(t.Type) { } else if Isptr[t.Etype] && Isfixedarray(t.Elem()) {
tp = t.Type tp = t.Elem()
n.Type = typSlice(tp.Type) n.Type = typSlice(tp.Elem())
dowidth(n.Type) dowidth(n.Type)
n.Op = OSLICEARR n.Op = OSLICEARR
} else if Isslice(t) { } else if Isslice(t) {
@ -1189,9 +1189,9 @@ OpSwitch:
} }
var tp *Type var tp *Type
if Isptr[t.Etype] && Isfixedarray(t.Type) { if Isptr[t.Etype] && Isfixedarray(t.Elem()) {
tp = t.Type tp = t.Elem()
n.Type = typSlice(tp.Type) n.Type = typSlice(tp.Elem())
dowidth(n.Type) dowidth(n.Type)
n.Op = OSLICE3ARR n.Op = OSLICE3ARR
} else if Isslice(t) { } else if Isslice(t) {
@ -1622,7 +1622,7 @@ OpSwitch:
return n return n
} }
if Istype(t.Type, TUINT8) && Istype(args.Second().Type, TSTRING) { if Istype(t.Elem(), TUINT8) && Istype(args.Second().Type, TSTRING) {
args.SetIndex(1, defaultlit(args.Index(1), Types[TSTRING])) args.SetIndex(1, defaultlit(args.Index(1), Types[TSTRING]))
break OpSwitch break OpSwitch
} }
@ -1634,8 +1634,8 @@ OpSwitch:
if funarg != nil { if funarg != nil {
_, it := IterFields(funarg) // Skip first field _, it := IterFields(funarg) // Skip first field
for t := it.Next(); t != nil; t = it.Next() { for t := it.Next(); t != nil; t = it.Next() {
if assignop(t.Type, n.Type.Type, nil) == 0 { if assignop(t.Type, n.Type.Elem(), nil) == 0 {
Yyerror("cannot append %v value to []%v", t.Type, n.Type.Type) Yyerror("cannot append %v value to []%v", t.Type, n.Type.Elem())
} }
} }
} else { } else {
@ -1644,7 +1644,7 @@ OpSwitch:
if n.Type == nil { if n.Type == nil {
continue continue
} }
as[i] = assignconv(n, t.Type, "append") as[i] = assignconv(n, t.Elem(), "append")
} }
} }
@ -1684,7 +1684,7 @@ OpSwitch:
// copy([]byte, string) // copy([]byte, string)
if Isslice(n.Left.Type) && n.Right.Type.Etype == TSTRING { if Isslice(n.Left.Type) && n.Right.Type.Etype == TSTRING {
if Eqtype(n.Left.Type.Type, bytetype) { if Eqtype(n.Left.Type.Elem(), bytetype) {
break OpSwitch break OpSwitch
} }
Yyerror("arguments to copy have different element types: %v and string", Tconv(n.Left.Type, FmtLong)) Yyerror("arguments to copy have different element types: %v and string", Tconv(n.Left.Type, FmtLong))
@ -1704,7 +1704,7 @@ OpSwitch:
return n return n
} }
if !Eqtype(n.Left.Type.Type, n.Right.Type.Type) { if !Eqtype(n.Left.Type.Elem(), n.Right.Type.Elem()) {
Yyerror("arguments to copy have different element types: %v and %v", Tconv(n.Left.Type, FmtLong), Tconv(n.Right.Type, FmtLong)) Yyerror("arguments to copy have different element types: %v and %v", Tconv(n.Left.Type, FmtLong), Tconv(n.Right.Type, FmtLong))
n.Type = nil n.Type = nil
return n return n
@ -1978,7 +1978,7 @@ OpSwitch:
if t.Etype == TSTRING { if t.Etype == TSTRING {
n.Type = Ptrto(Types[TUINT8]) n.Type = Ptrto(Types[TUINT8])
} else { } else {
n.Type = Ptrto(t.Type) n.Type = Ptrto(t.Elem())
} }
break OpSwitch break OpSwitch
@ -2299,7 +2299,7 @@ func implicitstar(n *Node) *Node {
if t == nil || !Isptr[t.Etype] { if t == nil || !Isptr[t.Etype] {
return n return n
} }
t = t.Type t = t.Elem()
if t == nil { if t == nil {
return n return n
} }
@ -2435,7 +2435,7 @@ func looktypedot(n *Node, t *Type, dostrcmp int) bool {
func derefall(t *Type) *Type { func derefall(t *Type) *Type {
for t != nil && t.Etype == Tptr { for t != nil && t.Etype == Tptr {
t = t.Type t = t.Elem()
} }
return t return t
} }
@ -2506,26 +2506,26 @@ func lookdot(n *Node, t *Type, dostrcmp int) *Field {
dowidth(tt) dowidth(tt)
rcvr := f2.Type.Recv().Type rcvr := f2.Type.Recv().Type
if !Eqtype(rcvr, tt) { if !Eqtype(rcvr, tt) {
if rcvr.Etype == Tptr && Eqtype(rcvr.Type, tt) { if rcvr.Etype == Tptr && Eqtype(rcvr.Elem(), tt) {
checklvalue(n.Left, "call pointer method on") checklvalue(n.Left, "call pointer method on")
n.Left = Nod(OADDR, n.Left, nil) n.Left = Nod(OADDR, n.Left, nil)
n.Left.Implicit = true n.Left.Implicit = true
n.Left = typecheck(n.Left, Etype|Erv) n.Left = typecheck(n.Left, Etype|Erv)
} else if tt.Etype == Tptr && rcvr.Etype != Tptr && Eqtype(tt.Type, rcvr) { } else if tt.Etype == Tptr && rcvr.Etype != Tptr && Eqtype(tt.Elem(), rcvr) {
n.Left = Nod(OIND, n.Left, nil) n.Left = Nod(OIND, n.Left, nil)
n.Left.Implicit = true n.Left.Implicit = true
n.Left = typecheck(n.Left, Etype|Erv) n.Left = typecheck(n.Left, Etype|Erv)
} else if tt.Etype == Tptr && tt.Type.Etype == Tptr && Eqtype(derefall(tt), derefall(rcvr)) { } else if tt.Etype == Tptr && tt.Elem().Etype == Tptr && Eqtype(derefall(tt), derefall(rcvr)) {
Yyerror("calling method %v with receiver %v requires explicit dereference", n.Sym, Nconv(n.Left, FmtLong)) Yyerror("calling method %v with receiver %v requires explicit dereference", n.Sym, Nconv(n.Left, FmtLong))
for tt.Etype == Tptr { for tt.Etype == Tptr {
// Stop one level early for method with pointer receiver. // Stop one level early for method with pointer receiver.
if rcvr.Etype == Tptr && tt.Type.Etype != Tptr { if rcvr.Etype == Tptr && tt.Elem().Etype != Tptr {
break break
} }
n.Left = Nod(OIND, n.Left, nil) n.Left = Nod(OIND, n.Left, nil)
n.Left.Implicit = true n.Left.Implicit = true
n.Left = typecheck(n.Left, Etype|Erv) n.Left = typecheck(n.Left, Etype|Erv)
tt = tt.Type tt = tt.Elem()
} }
} else { } else {
Fatalf("method mismatch: %v for %v", rcvr, tt) Fatalf("method mismatch: %v for %v", rcvr, tt)
@ -2612,11 +2612,11 @@ func typecheckaste(op Op, call *Node, isddd bool, tstruct *Type, nl Nodes, desc
for _, tl := range tstruct.Fields().Slice() { for _, tl := range tstruct.Fields().Slice() {
if tl.Isddd { if tl.Isddd {
for ; tn != nil; tn = it.Next() { for ; tn != nil; tn = it.Next() {
if assignop(tn.Type, tl.Type.Type, &why) == 0 { if assignop(tn.Type, tl.Type.Elem(), &why) == 0 {
if call != nil { if call != nil {
Yyerror("cannot use %v as type %v in argument to %v%s", tn.Type, tl.Type.Type, call, why) Yyerror("cannot use %v as type %v in argument to %v%s", tn.Type, tl.Type.Elem(), call, why)
} else { } else {
Yyerror("cannot use %v as type %v in %s%s", tn.Type, tl.Type.Type, desc(), why) Yyerror("cannot use %v as type %v in %s%s", tn.Type, tl.Type.Elem(), desc(), why)
} }
} }
} }
@ -2693,7 +2693,7 @@ func typecheckaste(op Op, call *Node, isddd bool, tstruct *Type, nl Nodes, desc
n = nl.Index(i) n = nl.Index(i)
setlineno(n) setlineno(n)
if n.Type != nil { if n.Type != nil {
nl.SetIndex(i, assignconvfn(n, t.Type, desc)) nl.SetIndex(i, assignconvfn(n, t.Elem(), desc))
} }
} }
@ -2846,7 +2846,7 @@ func iscomptype(t *Type) bool {
return true return true
case TPTR32, TPTR64: case TPTR32, TPTR64:
switch t.Type.Etype { switch t.Elem().Etype {
case TARRAY, TSTRUCT, TMAP: case TARRAY, TSTRUCT, TMAP:
return true return true
} }
@ -2914,7 +2914,7 @@ func typecheckcomplit(n *Node) *Node {
// For better or worse, we don't allow pointers as the composite literal type, // For better or worse, we don't allow pointers as the composite literal type,
// except when using the &T syntax, which sets implicit on the OIND. // except when using the &T syntax, which sets implicit on the OIND.
if !n.Right.Implicit { if !n.Right.Implicit {
Yyerror("invalid pointer type %v for composite literal (use &%v instead)", t, t.Type) Yyerror("invalid pointer type %v for composite literal (use &%v instead)", t, t.Elem())
n.Type = nil n.Type = nil
return n return n
} }
@ -2926,7 +2926,7 @@ func typecheckcomplit(n *Node) *Node {
return n return n
} }
t = t.Type t = t.Elem()
} }
var r *Node var r *Node
@ -2979,10 +2979,10 @@ func typecheckcomplit(n *Node) *Node {
} }
r = l.Right r = l.Right
pushtype(r, t.Type) pushtype(r, t.Elem())
r = typecheck(r, Erv) r = typecheck(r, Erv)
r = defaultlit(r, t.Type) r = defaultlit(r, t.Elem())
l.Right = assignconv(r, t.Type, "array or slice literal") l.Right = assignconv(r, t.Elem(), "array or slice literal")
} }
if t.isDDDArray() { if t.isDDDArray() {
@ -3440,7 +3440,7 @@ func stringtoarraylit(n *Node) *Node {
s := n.Left.Val().U.(string) s := n.Left.Val().U.(string)
var l []*Node var l []*Node
if n.Type.Type.Etype == TUINT8 { if n.Type.Elem().Etype == TUINT8 {
// []byte // []byte
for i := 0; i < len(s); i++ { for i := 0; i < len(s); i++ {
l = append(l, Nod(OKEY, Nodintconst(int64(i)), Nodintconst(int64(s[0])))) l = append(l, Nod(OKEY, Nodintconst(int64(i)), Nodintconst(int64(s[0]))))

View File

@ -365,7 +365,7 @@ func isSmallMakeSlice(n *Node) bool {
} }
t := n.Type t := n.Type
return Smallintconst(l) && Smallintconst(r) && (t.Type.Width == 0 || r.Val().U.(*Mpint).Int64() < (1<<16)/t.Type.Width) return Smallintconst(l) && Smallintconst(r) && (t.Elem().Width == 0 || r.Val().U.(*Mpint).Int64() < (1<<16)/t.Elem().Width)
} }
// walk the whole tree of the body of an // walk the whole tree of the body of an
@ -518,7 +518,7 @@ opswitch:
case ODOTPTR: case ODOTPTR:
usefield(n) usefield(n)
if n.Op == ODOTPTR && n.Left.Type.Type.Width == 0 { if n.Op == ODOTPTR && n.Left.Type.Elem().Width == 0 {
// No actual copy will be generated, so emit an explicit nil check. // No actual copy will be generated, so emit an explicit nil check.
n.Left = cheapexpr(n.Left, init) n.Left = cheapexpr(n.Left, init)
@ -542,7 +542,7 @@ opswitch:
t := n.Left.Type t := n.Left.Type
if Isptr[t.Etype] { if Isptr[t.Etype] {
t = t.Type t = t.Elem()
} }
if Isfixedarray(t) { if Isfixedarray(t) {
safeexpr(n.Left, init) safeexpr(n.Left, init)
@ -1155,7 +1155,7 @@ opswitch:
} }
t := n.Left.Type t := n.Left.Type
if t != nil && Isptr[t.Etype] { if t != nil && Isptr[t.Etype] {
t = t.Type t = t.Elem()
} }
if Isfixedarray(t) { if Isfixedarray(t) {
n.Bounded = bounded(r, t.Bound) n.Bounded = bounded(r, t.Bound)
@ -1268,10 +1268,10 @@ opswitch:
case ONEW: case ONEW:
if n.Esc == EscNone { if n.Esc == EscNone {
if n.Type.Type.Width >= 1<<16 { if n.Type.Elem().Width >= 1<<16 {
Fatalf("large ONEW with EscNone: %v", n) Fatalf("large ONEW with EscNone: %v", n)
} }
r := temp(n.Type.Type) r := temp(n.Type.Elem())
r = Nod(OAS, r, nil) // zero temp r = Nod(OAS, r, nil) // zero temp
r = typecheck(r, Etop) r = typecheck(r, Etop)
init.Append(r) init.Append(r)
@ -1279,7 +1279,7 @@ opswitch:
r = typecheck(r, Erv) r = typecheck(r, Erv)
n = r n = r
} else { } else {
n = callnew(n.Type.Type) n = callnew(n.Type.Elem())
} }
// If one argument to the comparison is an empty string, // If one argument to the comparison is an empty string,
@ -1410,7 +1410,7 @@ opswitch:
} }
// var arr [r]T // var arr [r]T
// n = arr[:l] // n = arr[:l]
t = aindex(r, t.Type) // [r]T t = aindex(r, t.Elem()) // [r]T
var_ := temp(t) var_ := temp(t)
a := Nod(OAS, var_, nil) // zero temp a := Nod(OAS, var_, nil) // zero temp
a = typecheck(a, Etop) a = typecheck(a, Etop)
@ -1424,7 +1424,7 @@ opswitch:
// makeslice(t *Type, nel int64, max int64) (ary []any) // makeslice(t *Type, nel int64, max int64) (ary []any)
fn := syslook("makeslice") fn := syslook("makeslice")
fn = substArgTypes(fn, t.Type) // any-1 fn = substArgTypes(fn, t.Elem()) // any-1
n = mkcall1(fn, n.Type, init, typename(n.Type), conv(l, Types[TINT64]), conv(r, Types[TINT64])) n = mkcall1(fn, n.Type, init, typename(n.Type), conv(l, Types[TINT64]), conv(r, Types[TINT64]))
} }
@ -1538,7 +1538,7 @@ opswitch:
case OSEND: case OSEND:
n1 := n.Right n1 := n.Right
n1 = assignconv(n1, n.Left.Type.Type, "chan send") n1 = assignconv(n1, n.Left.Type.Elem(), "chan send")
n1 = walkexpr(n1, init) n1 = walkexpr(n1, init)
n1 = Nod(OADDR, n1, nil) n1 = Nod(OADDR, n1, nil)
n = mkcall1(chanfn("chansend1", 2, n.Left.Type), nil, init, typename(n.Left.Type), n.Left, n1) n = mkcall1(chanfn("chansend1", 2, n.Left.Type), nil, init, typename(n.Left.Type), n.Left, n1)
@ -1715,7 +1715,7 @@ func mkdotargslice(lr0, nn []*Node, l *Field, fp int, init *Nodes, ddd *Node) []
esc = ddd.Esc esc = ddd.Esc
} }
tslice := typSlice(l.Type.Type) tslice := typSlice(l.Type.Elem())
var n *Node var n *Node
if len(lr0) == 0 { if len(lr0) == 0 {
@ -2633,9 +2633,9 @@ func chanfn(name string, n int, t *Type) *Node {
default: default:
Fatalf("chanfn %d", n) Fatalf("chanfn %d", n)
case 1: case 1:
fn = substArgTypes(fn, t.Type) fn = substArgTypes(fn, t.Elem())
case 2: case 2:
fn = substArgTypes(fn, t.Type, t.Type) fn = substArgTypes(fn, t.Elem(), t.Elem())
} }
return fn return fn
} }
@ -2772,7 +2772,7 @@ func appendslice(n *Node, init *Nodes) *Node {
// instantiate growslice(Type*, []any, int) []any // instantiate growslice(Type*, []any, int) []any
fn := syslook("growslice") fn := syslook("growslice")
fn = substArgTypes(fn, s.Type.Type, s.Type.Type) fn = substArgTypes(fn, s.Type.Elem(), s.Type.Elem())
// s = growslice(T, s, n) // s = growslice(T, s, n)
nif.Nbody.Set1(Nod(OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(s.Type), s, nn))) nif.Nbody.Set1(Nod(OAS, s, mkcall1(fn, s.Type, &nif.Ninit, typename(s.Type), s, nn)))
@ -2783,7 +2783,7 @@ func appendslice(n *Node, init *Nodes) *Node {
nt.Etype = 1 nt.Etype = 1
l = append(l, Nod(OAS, s, nt)) l = append(l, Nod(OAS, s, nt))
if haspointers(l1.Type.Type) { if haspointers(l1.Type.Elem()) {
// copy(s[len(l1):], l2) // copy(s[len(l1):], l2)
nptr1 := Nod(OSLICE, s, Nod(OKEY, Nod(OLEN, l1, nil), nil)) nptr1 := Nod(OSLICE, s, Nod(OKEY, Nod(OLEN, l1, nil), nil))
@ -2793,7 +2793,7 @@ func appendslice(n *Node, init *Nodes) *Node {
fn = substArgTypes(fn, l1.Type, l2.Type) fn = substArgTypes(fn, l1.Type, l2.Type)
var ln Nodes var ln Nodes
ln.Set(l) ln.Set(l)
nt := mkcall1(fn, Types[TINT], &ln, typename(l1.Type.Type), nptr1, nptr2) nt := mkcall1(fn, Types[TINT], &ln, typename(l1.Type.Elem()), nptr1, nptr2)
l = append(ln.Slice(), nt) l = append(ln.Slice(), nt)
} else if instrumenting { } else if instrumenting {
// rely on runtime to instrument copy. // rely on runtime to instrument copy.
@ -2811,7 +2811,7 @@ func appendslice(n *Node, init *Nodes) *Node {
fn = substArgTypes(fn, l1.Type, l2.Type) fn = substArgTypes(fn, l1.Type, l2.Type)
var ln Nodes var ln Nodes
ln.Set(l) ln.Set(l)
nt := mkcall1(fn, Types[TINT], &ln, nptr1, nptr2, Nodintconst(s.Type.Type.Width)) nt := mkcall1(fn, Types[TINT], &ln, nptr1, nptr2, Nodintconst(s.Type.Elem().Width))
l = append(ln.Slice(), nt) l = append(ln.Slice(), nt)
} else { } else {
// memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T)) // memmove(&s[len(l1)], &l2[0], len(l2)*sizeof(T))
@ -2823,13 +2823,13 @@ func appendslice(n *Node, init *Nodes) *Node {
nptr2 := Nod(OSPTR, l2, nil) nptr2 := Nod(OSPTR, l2, nil)
fn := syslook("memmove") fn := syslook("memmove")
fn = substArgTypes(fn, s.Type.Type, s.Type.Type) fn = substArgTypes(fn, s.Type.Elem(), s.Type.Elem())
var ln Nodes var ln Nodes
ln.Set(l) ln.Set(l)
nwid := cheapexpr(conv(Nod(OLEN, l2, nil), Types[TUINTPTR]), &ln) nwid := cheapexpr(conv(Nod(OLEN, l2, nil), Types[TUINTPTR]), &ln)
nwid = Nod(OMUL, nwid, Nodintconst(s.Type.Type.Width)) nwid = Nod(OMUL, nwid, Nodintconst(s.Type.Elem().Width))
nt := mkcall1(fn, nil, &ln, nptr1, nptr2, nwid) nt := mkcall1(fn, nil, &ln, nptr1, nptr2, nwid)
l = append(ln.Slice(), nt) l = append(ln.Slice(), nt)
} }
@ -2883,7 +2883,7 @@ func walkappend(n *Node, init *Nodes, dst *Node) *Node {
// Resolve slice type of multi-valued return. // Resolve slice type of multi-valued return.
if Istype(nsrc.Type, TSTRUCT) { if Istype(nsrc.Type, TSTRUCT) {
nsrc.Type = nsrc.Type.Type.Type nsrc.Type = nsrc.Type.Elem().Elem()
} }
argc := n.List.Len() - 1 argc := n.List.Len() - 1
if argc < 1 { if argc < 1 {
@ -2906,7 +2906,7 @@ func walkappend(n *Node, init *Nodes, dst *Node) *Node {
nx.Left = Nod(OLT, Nod(OSUB, Nod(OCAP, ns, nil), Nod(OLEN, ns, nil)), na) nx.Left = Nod(OLT, Nod(OSUB, Nod(OCAP, ns, nil), Nod(OLEN, ns, nil)), na)
fn := syslook("growslice") // growslice(<type>, old []T, mincap int) (ret []T) fn := syslook("growslice") // growslice(<type>, old []T, mincap int) (ret []T)
fn = substArgTypes(fn, ns.Type.Type, ns.Type.Type) fn = substArgTypes(fn, ns.Type.Elem(), ns.Type.Elem())
nx.Nbody.Set1(Nod(OAS, ns, nx.Nbody.Set1(Nod(OAS, ns,
mkcall1(fn, ns.Type, &nx.Ninit, typename(ns.Type), ns, mkcall1(fn, ns.Type, &nx.Ninit, typename(ns.Type), ns,
@ -2949,9 +2949,9 @@ func walkappend(n *Node, init *Nodes, dst *Node) *Node {
// Also works if b is a string. // Also works if b is a string.
// //
func copyany(n *Node, init *Nodes, runtimecall bool) *Node { func copyany(n *Node, init *Nodes, runtimecall bool) *Node {
if haspointers(n.Left.Type.Type) { if haspointers(n.Left.Type.Elem()) {
fn := writebarrierfn("typedslicecopy", n.Left.Type, n.Right.Type) fn := writebarrierfn("typedslicecopy", n.Left.Type, n.Right.Type)
return mkcall1(fn, n.Type, init, typename(n.Left.Type.Type), n.Left, n.Right) return mkcall1(fn, n.Type, init, typename(n.Left.Type.Elem()), n.Left, n.Right)
} }
if runtimecall { if runtimecall {
@ -2962,7 +2962,7 @@ func copyany(n *Node, init *Nodes, runtimecall bool) *Node {
fn = syslook("slicecopy") fn = syslook("slicecopy")
} }
fn = substArgTypes(fn, n.Left.Type, n.Right.Type) fn = substArgTypes(fn, n.Left.Type, n.Right.Type)
return mkcall1(fn, n.Type, init, n.Left, n.Right, Nodintconst(n.Left.Type.Type.Width)) return mkcall1(fn, n.Type, init, n.Left, n.Right, Nodintconst(n.Left.Type.Elem().Width))
} }
n.Left = walkexpr(n.Left, init) n.Left = walkexpr(n.Left, init)
@ -2991,10 +2991,10 @@ func copyany(n *Node, init *Nodes, runtimecall bool) *Node {
// Call memmove. // Call memmove.
fn := syslook("memmove") fn := syslook("memmove")
fn = substArgTypes(fn, nl.Type.Type, nl.Type.Type) fn = substArgTypes(fn, nl.Type.Elem(), nl.Type.Elem())
nwid := temp(Types[TUINTPTR]) nwid := temp(Types[TUINTPTR])
l = append(l, Nod(OAS, nwid, conv(nlen, Types[TUINTPTR]))) l = append(l, Nod(OAS, nwid, conv(nlen, Types[TUINTPTR])))
nwid = Nod(OMUL, nwid, Nodintconst(nl.Type.Type.Width)) nwid = Nod(OMUL, nwid, Nodintconst(nl.Type.Elem().Width))
l = append(l, mkcall1(fn, nil, init, nto, nfrm, nwid)) l = append(l, mkcall1(fn, nil, init, nto, nfrm, nwid))
typecheckslice(l, Etop) typecheckslice(l, Etop)
@ -3136,7 +3136,7 @@ func walkcompare(n *Node, init *Nodes) *Node {
} }
var expr *Node var expr *Node
if t.Etype == TARRAY && t.Bound <= 4 && issimple[t.Type.Etype] { if t.Etype == TARRAY && t.Bound <= 4 && issimple[t.Elem().Etype] {
// Four or fewer elements of a basic type. // Four or fewer elements of a basic type.
// Unroll comparisons. // Unroll comparisons.
var li *Node var li *Node
@ -3773,7 +3773,7 @@ func usefield(n *Node) {
t := n.Left.Type t := n.Left.Type
if Isptr[t.Etype] { if Isptr[t.Etype] {
t = t.Type t = t.Elem()
} }
field := dotField[typeSym{t.Orig, n.Sym}] field := dotField[typeSym{t.Orig, n.Sym}]
if field == nil { if field == nil {
@ -3785,7 +3785,7 @@ func usefield(n *Node) {
outer := n.Left.Type outer := n.Left.Type
if Isptr[outer.Etype] { if Isptr[outer.Etype] {
outer = outer.Type outer = outer.Elem()
} }
if outer.Sym == nil { if outer.Sym == nil {
Yyerror("tracked field must be in named struct type") Yyerror("tracked field must be in named struct type")