1
0
mirror of https://github.com/golang/go synced 2024-11-23 01:50:04 -07:00

cmd/compile: get rid of Type's {This,In,Out}tuple fields

Boolean expressions involving t.Thistuple were converted to use
t.Recv(), because it's a bit clearer and will hopefully reveal cases
where we could remove redundant calls to t.Recv() (in followup CLs).

The other cases were all converted to use t.Recvs().NumFields(),
t.Params().NumFields(), or t.Results().NumFields().

Change-Id: I4df91762e7dc4b2ddae35995f8dd604a52c09b09
Reviewed-on: https://go-review.googlesource.com/20796
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Matthew Dempsky 2016-03-17 01:47:16 -07:00
parent d447613875
commit c837761b52
15 changed files with 60 additions and 80 deletions

View File

@ -595,7 +595,7 @@ func makepartialcall(fn *Node, t0 *Type, meth *Node) *Node {
call := Nod(OCALL, Nod(OXDOT, ptr, meth), nil)
call.List.Set(callargs)
call.Isddd = ddd
if t0.Outtuple == 0 {
if t0.Results().NumFields() == 0 {
body = append(body, call)
} else {
n := Nod(OAS2, nil, nil)

View File

@ -655,37 +655,31 @@ func funcargs2(t *Type) {
Fatalf("funcargs2 %v", t)
}
if t.Thistuple != 0 {
for _, ft := range t.Recvs().Fields().Slice() {
if ft.Nname == nil || ft.Nname.Sym == nil {
continue
}
n := ft.Nname // no need for newname(ft->nname->sym)
n.Type = ft.Type
declare(n, PPARAM)
for _, ft := range t.Recvs().Fields().Slice() {
if ft.Nname == nil || ft.Nname.Sym == nil {
continue
}
n := ft.Nname // no need for newname(ft->nname->sym)
n.Type = ft.Type
declare(n, PPARAM)
}
if t.Intuple != 0 {
for _, ft := range t.Params().Fields().Slice() {
if ft.Nname == nil || ft.Nname.Sym == nil {
continue
}
n := ft.Nname
n.Type = ft.Type
declare(n, PPARAM)
for _, ft := range t.Params().Fields().Slice() {
if ft.Nname == nil || ft.Nname.Sym == nil {
continue
}
n := ft.Nname
n.Type = ft.Type
declare(n, PPARAM)
}
if t.Outtuple != 0 {
for _, ft := range t.Results().Fields().Slice() {
if ft.Nname == nil || ft.Nname.Sym == nil {
continue
}
n := ft.Nname
n.Type = ft.Type
declare(n, PPARAMOUT)
for _, ft := range t.Results().Fields().Slice() {
if ft.Nname == nil || ft.Nname.Sym == nil {
continue
}
n := ft.Nname
n.Type = ft.Type
declare(n, PPARAMOUT)
}
}
@ -1068,13 +1062,8 @@ func functype0(t *Type, this *Node, in, out []*Node) {
t.Broke = true
}
if this != nil {
t.Thistuple = 1
}
t.Outtuple = len(out)
t.Intuple = len(in)
t.Outnamed = false
if t.Outtuple > 0 && out[0].Left != nil && out[0].Left.Orig != nil {
if len(out) > 0 && out[0].Left != nil && out[0].Left.Orig != nil {
s := out[0].Left.Orig.Sym
if s != nil && (s.Name[0] != '~' || s.Name[1] != 'r') { // ~r%d is the name invented for an unnamed result
t.Outnamed = true

View File

@ -810,7 +810,7 @@ func esc(e *EscState, n *Node, up *Node) {
case ORETURN:
ll := n.List
if n.List.Len() == 1 && Curfn.Type.Outtuple > 1 {
if n.List.Len() == 1 && Curfn.Type.Results().NumFields() > 1 {
// OAS2FUNC in disguise
// esccall already done on n->list->n
// tie n->list->n->escretval to curfn->dcl PPARAMOUT's

View File

@ -130,7 +130,7 @@ func reexportdep(n *Node) {
}
// nodes for method calls.
if n.Type == nil || n.Type.Thistuple > 0 {
if n.Type == nil || n.Type.Recv() != nil {
break
}
fallthrough

View File

@ -630,7 +630,7 @@ func typefmt(t *Type, flag FmtFlag) string {
if flag&FmtShort != 0 {
// no leading func
} else {
if t.Thistuple != 0 {
if t.Recv() != nil {
buf.WriteString("method")
buf.WriteString(Tconv(t.Recvs(), 0))
buf.WriteString(" ")
@ -639,7 +639,7 @@ func typefmt(t *Type, flag FmtFlag) string {
}
buf.WriteString(Tconv(t.Params(), 0))
switch t.Outtuple {
switch t.Results().NumFields() {
case 0:
break

View File

@ -34,7 +34,7 @@ import (
// Get the function's package. For ordinary functions it's on the ->sym, but for imported methods
// the ->sym can be re-used in the local package, so peel it off the receiver's type.
func fnpkg(fn *Node) *Pkg {
if fn.Type.Thistuple != 0 {
if fn.Type.Recv() != nil {
// method
rcvr := fn.Type.Recv().Type
@ -592,7 +592,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
}
// assign receiver.
if fn.Type.Thistuple != 0 && n.Left.Op == ODOTMETH {
if fn.Type.Recv() != nil && n.Left.Op == ODOTMETH {
// method call with a receiver.
t := fn.Type.Recv()
@ -635,8 +635,8 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
if n.List.Len() == 1 {
switch n.List.First().Op {
case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH:
if n.List.First().Left.Type.Outtuple > 1 {
multiret = n.List.First().Left.Type.Outtuple - 1
if n.List.First().Left.Type.Results().NumFields() > 1 {
multiret = n.List.First().Left.Type.Results().NumFields() - 1
}
}
}
@ -644,9 +644,9 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
if variadic {
varargcount = n.List.Len() + multiret
if n.Left.Op != ODOTMETH {
varargcount -= fn.Type.Thistuple
varargcount -= fn.Type.Recvs().NumFields()
}
varargcount -= fn.Type.Intuple - 1
varargcount -= fn.Type.Params().NumFields() - 1
}
// assign arguments to the parameters' temp names
@ -656,7 +656,7 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
li := 0
// TODO: if len(nlist) == 1 but multiple args, check that n->list->n is a call?
if fn.Type.Thistuple != 0 && n.Left.Op != ODOTMETH {
if fn.Type.Recv() != nil && n.Left.Op != ODOTMETH {
// non-method call to method
if n.List.Len() == 0 {
Fatalf("non-method call to method without first arg: %v", Nconv(n, FmtSign))

View File

@ -326,14 +326,14 @@ func ismulticall(l Nodes) bool {
}
// call must return multiple values
return n.Left.Type.Outtuple > 1
return n.Left.Type.Results().NumFields() > 1
}
// Copyret emits t1, t2, ... = n, where n is a function call,
// and then returns the list t1, t2, ....
func copyret(n *Node, order *Order) []*Node {
if n.Type.Etype != TSTRUCT || !n.Type.Funarg {
Fatalf("copyret %v %d", n.Type, n.Left.Type.Outtuple)
Fatalf("copyret %v %d", n.Type, n.Left.Type.Results().NumFields())
}
var l1 []*Node

View File

@ -147,18 +147,18 @@ func emitptrargsmap() {
nptr := int(Curfn.Type.Argwid / int64(Widthptr))
bv := bvalloc(int32(nptr) * 2)
nbitmap := 1
if Curfn.Type.Outtuple > 0 {
if Curfn.Type.Results().NumFields() > 0 {
nbitmap = 2
}
off := duint32(sym, 0, uint32(nbitmap))
off = duint32(sym, off, uint32(bv.n))
var xoffset int64
if Curfn.Type.Thistuple > 0 {
if Curfn.Type.Recv() != nil {
xoffset = 0
onebitwalktype1(Curfn.Type.Recvs(), &xoffset, bv)
}
if Curfn.Type.Intuple > 0 {
if Curfn.Type.Params().NumFields() > 0 {
xoffset = 0
onebitwalktype1(Curfn.Type.Params(), &xoffset, bv)
}
@ -166,7 +166,7 @@ func emitptrargsmap() {
for j := 0; int32(j) < bv.n; j += 32 {
off = duint32(sym, off, bv.b[j/32])
}
if Curfn.Type.Outtuple > 0 {
if Curfn.Type.Results().NumFields() > 0 {
xoffset = 0
onebitwalktype1(Curfn.Type.Results(), &xoffset, bv)
for j := 0; int32(j) < bv.n; j += 32 {
@ -503,7 +503,7 @@ func genlegacy(ptxt *obj.Prog, gcargs, gclocals *Sym) {
lineno = Curfn.Func.Endlineno
}
if Curfn.Type.Outtuple != 0 {
if Curfn.Type.Results().NumFields() != 0 {
Ginscall(throwreturn, 0)
}

View File

@ -286,7 +286,7 @@ func methods(t *Type) []*Sig {
// generating code if necessary.
var ms []*Sig
for _, f := range mt.AllMethods().Slice() {
if f.Type.Etype != TFUNC || f.Type.Thistuple == 0 {
if f.Type.Etype != TFUNC || f.Type.Recv() == nil {
Fatalf("non-method on %v method %v %v\n", mt, f.Sym, f)
}
if f.Type.Recv() == nil {
@ -1041,8 +1041,8 @@ ok:
}
ot = dcommontype(s, ot, t)
inCount := t.Thistuple + t.Intuple
outCount := t.Outtuple
inCount := t.Recvs().NumFields() + t.Params().NumFields()
outCount := t.Results().NumFields()
if isddd {
outCount |= 1 << 15
}
@ -1052,7 +1052,7 @@ ok:
ot += 4 // align for *rtype
}
dataAdd := (inCount + t.Outtuple) * Widthptr
dataAdd := (inCount + t.Results().NumFields()) * Widthptr
ot = dextratype(s, ot, t, dataAdd)
// Array of rtype pointers follows funcType.

View File

@ -27,7 +27,7 @@ func TestSizeof(t *testing.T) {
{Name{}, 52, 80},
{Node{}, 92, 144},
{Sym{}, 60, 112},
{Type{}, 132, 224},
{Type{}, 116, 184},
}
for _, tt := range tests {

View File

@ -1556,7 +1556,7 @@ func lookdot0(s *Sym, t *Type, save **Field, ignorecase bool) int {
c := 0
if u.Etype == TSTRUCT || u.Etype == TINTER {
for _, f := range u.Fields().Slice() {
if f.Sym == s || (ignorecase && f.Type.Etype == TFUNC && f.Type.Thistuple > 0 && strings.EqualFold(f.Sym.Name, s.Name)) {
if f.Sym == s || (ignorecase && f.Type.Etype == TFUNC && f.Type.Recv() != nil && strings.EqualFold(f.Sym.Name, s.Name)) {
if save != nil {
*save = f
}
@ -1807,7 +1807,7 @@ func expandmeth(t *Type) {
}
// dotpath may have dug out arbitrary fields, we only want methods.
if f.Type.Etype != TFUNC || f.Type.Thistuple == 0 {
if f.Type.Etype != TFUNC || f.Type.Recv() == nil {
continue
}
@ -1981,7 +1981,7 @@ func genwrapper(rcvr *Type, method *Field, newnam *Sym, iface int) {
call := Nod(OCALL, dot, nil)
call.List.Set(args)
call.Isddd = isddd
if method.Type.Outtuple > 0 {
if method.Type.Results().NumFields() > 0 {
n := Nod(ORETURN, nil, nil)
n.List.Set1(call)
call = n
@ -2051,7 +2051,7 @@ func ifacelookdot(s *Sym, t *Type, followptr *bool, ignorecase bool) *Field {
}
}
if m.Type.Etype != TFUNC || m.Type.Thistuple == 0 {
if m.Type.Etype != TFUNC || m.Type.Recv() == nil {
Yyerror("%v.%v is a field, not a method", t, s)
return nil
}

View File

@ -112,22 +112,17 @@ type Type struct {
Broke bool // broken type definition.
Align uint8
Haspointers uint8 // 0 unknown, 1 no, 2 yes
Outnamed bool // on TFUNC
Nod *Node // canonical OTYPE node
Orig *Type // original type (type literal or predefined type)
Lineno int32
// TFUNC
Thistuple int
Outtuple int
Intuple int
Outnamed bool
Nod *Node // canonical OTYPE node
Orig *Type // original type (type literal or predefined type)
methods Fields
allMethods Fields
Sym *Sym
Vargen int32 // unique name for OTYPE/ONAME
Lineno int32
Nname *Node
Argwid int64

View File

@ -845,7 +845,7 @@ OpSwitch:
return
}
if n.Type.Etype != TFUNC || n.Type.Thistuple != 1 {
if n.Type.Etype != TFUNC || n.Type.Recv() == nil {
Yyerror("type %v has no method %v", n.Left.Type, Sconv(n.Right.Sym, FmtShort))
n.Type = nil
n.Type = nil
@ -1327,11 +1327,11 @@ OpSwitch:
typecheckaste(OCALL, n.Left, n.Isddd, t.Params(), n.List, func() string { return fmt.Sprintf("argument to %v", n.Left) })
ok |= Etop
if t.Outtuple == 0 {
if t.Results().NumFields() == 0 {
break OpSwitch
}
ok |= Erv
if t.Outtuple == 1 {
if t.Results().NumFields() == 1 {
n.Type = l.Type.Results().Field(0).Type
if n.Op == OCALLFUNC && n.Left.Op == ONAME && (compiling_runtime != 0 || n.Left.Sym.Pkg == Runtimepkg) && n.Left.Sym.Name == "getg" {
@ -1445,8 +1445,8 @@ OpSwitch:
}
t := n.List.First().Left.Type
if t.Outtuple != 2 {
Yyerror("invalid operation: complex expects two arguments, %v returns %d results", n.List.First(), t.Outtuple)
if t.Results().NumFields() != 2 {
Yyerror("invalid operation: complex expects two arguments, %v returns %d results", n.List.First(), t.Results().NumFields())
n.Type = nil
return
}
@ -3957,7 +3957,7 @@ func (n *Node) isterminating() bool {
}
func checkreturn(fn *Node) {
if fn.Type.Outtuple != 0 && len(fn.Nbody.Slice()) != 0 {
if fn.Type.Results().NumFields() != 0 && len(fn.Nbody.Slice()) != 0 {
markbreaklist(fn.Nbody, nil)
if !fn.Nbody.isterminating() {
yyerrorl(fn.Func.Endlineno, "missing return at end of function")

View File

@ -387,10 +387,6 @@ func lexinit1() {
*f.RecvsP() = rcvr
*f.ResultsP() = out
*f.ParamsP() = in
f.Thistuple = 1
f.Intuple = 0
f.Outnamed = false
f.Outtuple = 1
t := typ(TINTER)
field = newField()

View File

@ -657,7 +657,7 @@ opswitch:
// Update type of OCALLFUNC node.
// Output arguments had not changed, but their offsets could.
if n.Left.Type.Outtuple == 1 {
if n.Left.Type.Results().NumFields() == 1 {
n.Type = n.Left.Type.Results().Field(0).Type
} else {
n.Type = n.Left.Type.Results()
@ -2634,11 +2634,11 @@ func vmkcall(fn *Node, t *Type, init *Nodes, va []*Node) *Node {
Fatalf("mkcall %v %v", fn, fn.Type)
}
n := fn.Type.Intuple
n := fn.Type.Params().NumFields()
r := Nod(OCALL, fn, nil)
r.List.Set(va[:n])
if fn.Type.Outtuple > 0 {
if fn.Type.Results().NumFields() > 0 {
typecheck(&r, Erv|Efnstruct)
} else {
typecheck(&r, Etop)