[dev.regabi] cmd/compile: use Node getters and setters [generated]

Now that we have all the getters and setters defined, use them
and unexport all the actual Node fields. This is the next step
toward replacing Node with an interface.

[git-generate]
cd src/cmd/compile/internal/gc
rf '
        ex . ../ir ../ssa {
                import "cmd/compile/internal/ir"
                import "cmd/compile/internal/types"
                import "cmd/internal/src"
                var n, x *ir.Node
                var op ir.Op
                var t *types.Type
                var f *ir.Func
                var m *ir.Name
                var s *types.Sym
                var p src.XPos
                var i int64
                var e uint16
                var nodes ir.Nodes

                n.Op = op    -> n.SetOp(op)
                n.Left = x   -> n.SetLeft(x)
                n.Right = x  -> n.SetRight(x)
                n.Orig = x -> n.SetOrig(x)
                n.Type = t -> n.SetType(t)
                n.Func = f -> n.SetFunc(f)
                n.Name = m -> n.SetName(m)
                n.Sym = s -> n.SetSym(s)
                n.Pos = p -> n.SetPos(p)
                n.Xoffset = i -> n.SetXoffset(i)
                n.Esc = e -> n.SetEsc(e)

                n.Ninit.Append -> n.PtrNinit().Append
                n.Ninit.AppendNodes -> n.PtrNinit().AppendNodes
                n.Ninit.MoveNodes -> n.PtrNinit().MoveNodes
                n.Ninit.Prepend -> n.PtrNinit().Prepend
                n.Ninit.Set -> n.PtrNinit().Set
                n.Ninit.Set1 -> n.PtrNinit().Set1
                n.Ninit.Set2 -> n.PtrNinit().Set2
                n.Ninit.Set3 -> n.PtrNinit().Set3
                &n.Ninit -> n.PtrNinit()
                n.Ninit = nodes -> n.SetNinit(nodes)

                n.Nbody.Append -> n.PtrNbody().Append
                n.Nbody.AppendNodes -> n.PtrNbody().AppendNodes
                n.Nbody.MoveNodes -> n.PtrNbody().MoveNodes
                n.Nbody.Prepend -> n.PtrNbody().Prepend
                n.Nbody.Set -> n.PtrNbody().Set
                n.Nbody.Set1 -> n.PtrNbody().Set1
                n.Nbody.Set2 -> n.PtrNbody().Set2
                n.Nbody.Set3 -> n.PtrNbody().Set3
                &n.Nbody -> n.PtrNbody()
                n.Nbody = nodes -> n.SetNbody(nodes)

                n.List.Append -> n.PtrList().Append
                n.List.AppendNodes -> n.PtrList().AppendNodes
                n.List.MoveNodes -> n.PtrList().MoveNodes
                n.List.Prepend -> n.PtrList().Prepend
                n.List.Set -> n.PtrList().Set
                n.List.Set1 -> n.PtrList().Set1
                n.List.Set2 -> n.PtrList().Set2
                n.List.Set3 -> n.PtrList().Set3
                &n.List -> n.PtrList()
                n.List = nodes -> n.SetList(nodes)

                n.Rlist.Append -> n.PtrRlist().Append
                n.Rlist.AppendNodes -> n.PtrRlist().AppendNodes
                n.Rlist.MoveNodes -> n.PtrRlist().MoveNodes
                n.Rlist.Prepend -> n.PtrRlist().Prepend
                n.Rlist.Set -> n.PtrRlist().Set
                n.Rlist.Set1 -> n.PtrRlist().Set1
                n.Rlist.Set2 -> n.PtrRlist().Set2
                n.Rlist.Set3 -> n.PtrRlist().Set3
                &n.Rlist -> n.PtrRlist()
                n.Rlist = nodes -> n.SetRlist(nodes)
        }
        ex . ../ir ../ssa {
                import "cmd/compile/internal/ir"

                var n *ir.Node
                n.Op         -> n.GetOp()
                n.Left       -> n.GetLeft()
                n.Right      -> n.GetRight()
                n.Orig -> n.GetOrig()
                n.Type -> n.GetType()
                n.Func -> n.GetFunc()
                n.Name -> n.GetName()
                n.Sym -> n.GetSym()
                n.Pos -> n.GetPos()
                n.Xoffset -> n.GetXoffset()
                n.Esc -> n.GetEsc()

                avoid (*ir.Node).PtrNinit
                avoid (*ir.Node).PtrNbody
                avoid (*ir.Node).PtrList
                avoid (*ir.Node).PtrRlist

                n.Ninit -> n.GetNinit()
                n.Nbody -> n.GetNbody()
                n.List -> n.GetList()
                n.Rlist -> n.GetRlist()
        }
'

cd ../ir
rf '
        mv Node.Op Node.op
        mv Node.GetOp Node.Op

        mv Node.Left Node.left
        mv Node.GetLeft Node.Left

        mv Node.Right Node.right
        mv Node.GetRight Node.Right

        mv Node.Orig Node.orig
        mv Node.GetOrig Node.Orig

        mv Node.Type Node.typ
        mv Node.GetType Node.Type

        mv Node.Func Node.fn
        mv Node.GetFunc Node.Func

        mv Node.Name Node.name
        mv Node.GetName Node.Name

        # All uses are in other Node methods already.
        mv Node.E Node.e

        mv Node.Sym Node.sym
        mv Node.GetSym Node.Sym

        mv Node.Pos Node.pos
        mv Node.GetPos Node.Pos

        mv Node.Esc Node.esc
        mv Node.GetEsc Node.Esc

	# While we are here, rename Xoffset to more idiomatic Offset.
        mv Node.Xoffset Node.offset
        mv Node.GetXoffset Node.Offset
	mv Node.SetXoffset Node.SetOffset

        # While we are here, rename Ninit, Nbody to more idiomatic Init, Body.
        mv Node.Ninit Node.init
        mv Node.GetNinit Node.Init
        mv Node.PtrNinit Node.PtrInit
        mv Node.SetNinit Node.SetInit
        mv Node.Nbody Node.body
        mv Node.GetNbody Node.Body
        mv Node.PtrNbody Node.PtrBody
        mv Node.SetNbody Node.SetBody
        mv Node.List Node.list
        mv Node.GetList Node.List
        mv Node.Rlist Node.rlist
        mv Node.GetRlist Node.Rlist

        # Unexport these
        mv Node.SetHasOpt Node.setHasOpt
        mv Node.SetHasVal Node.setHasVal
'

Change-Id: I9894f633375c5237a29b6d6d7b89ba181b56ca3a
Reviewed-on: https://go-review.googlesource.com/c/go/+/273009
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Russ Cox 2020-11-22 09:59:15 -05:00
parent 41ab6689ed
commit acb4d1cef1
44 changed files with 5188 additions and 5186 deletions

View file

@ -16,8 +16,8 @@ import (
// typecheckswitch typechecks a switch statement.
func typecheckswitch(n *ir.Node) {
typecheckslice(n.Ninit.Slice(), ctxStmt)
if n.Left != nil && n.Left.Op == ir.OTYPESW {
typecheckslice(n.Init().Slice(), ctxStmt)
if n.Left() != nil && n.Left().Op() == ir.OTYPESW {
typecheckTypeSwitch(n)
} else {
typecheckExprSwitch(n)
@ -25,27 +25,27 @@ func typecheckswitch(n *ir.Node) {
}
func typecheckTypeSwitch(n *ir.Node) {
n.Left.Right = typecheck(n.Left.Right, ctxExpr)
t := n.Left.Right.Type
n.Left().SetRight(typecheck(n.Left().Right(), ctxExpr))
t := n.Left().Right().Type()
if t != nil && !t.IsInterface() {
base.ErrorfAt(n.Pos, "cannot type switch on non-interface value %L", n.Left.Right)
base.ErrorfAt(n.Pos(), "cannot type switch on non-interface value %L", n.Left().Right())
t = nil
}
// We don't actually declare the type switch's guarded
// declaration itself. So if there are no cases, we won't
// notice that it went unused.
if v := n.Left.Left; v != nil && !ir.IsBlank(v) && n.List.Len() == 0 {
base.ErrorfAt(v.Pos, "%v declared but not used", v.Sym)
if v := n.Left().Left(); v != nil && !ir.IsBlank(v) && n.List().Len() == 0 {
base.ErrorfAt(v.Pos(), "%v declared but not used", v.Sym())
}
var defCase, nilCase *ir.Node
var ts typeSet
for _, ncase := range n.List.Slice() {
ls := ncase.List.Slice()
for _, ncase := range n.List().Slice() {
ls := ncase.List().Slice()
if len(ls) == 0 { // default:
if defCase != nil {
base.ErrorfAt(ncase.Pos, "multiple defaults in switch (first at %v)", ir.Line(defCase))
base.ErrorfAt(ncase.Pos(), "multiple defaults in switch (first at %v)", ir.Line(defCase))
} else {
defCase = ncase
}
@ -54,7 +54,7 @@ func typecheckTypeSwitch(n *ir.Node) {
for i := range ls {
ls[i] = typecheck(ls[i], ctxExpr|ctxType)
n1 := ls[i]
if t == nil || n1.Type == nil {
if t == nil || n1.Type() == nil {
continue
}
@ -63,36 +63,36 @@ func typecheckTypeSwitch(n *ir.Node) {
switch {
case ir.IsNil(n1): // case nil:
if nilCase != nil {
base.ErrorfAt(ncase.Pos, "multiple nil cases in type switch (first at %v)", ir.Line(nilCase))
base.ErrorfAt(ncase.Pos(), "multiple nil cases in type switch (first at %v)", ir.Line(nilCase))
} else {
nilCase = ncase
}
case n1.Op != ir.OTYPE:
base.ErrorfAt(ncase.Pos, "%L is not a type", n1)
case !n1.Type.IsInterface() && !implements(n1.Type, t, &missing, &have, &ptr) && !missing.Broke():
case n1.Op() != ir.OTYPE:
base.ErrorfAt(ncase.Pos(), "%L is not a type", n1)
case !n1.Type().IsInterface() && !implements(n1.Type(), t, &missing, &have, &ptr) && !missing.Broke():
if have != nil && !have.Broke() {
base.ErrorfAt(ncase.Pos, "impossible type switch case: %L cannot have dynamic type %v"+
" (wrong type for %v method)\n\thave %v%S\n\twant %v%S", n.Left.Right, n1.Type, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
base.ErrorfAt(ncase.Pos(), "impossible type switch case: %L cannot have dynamic type %v"+
" (wrong type for %v method)\n\thave %v%S\n\twant %v%S", n.Left().Right(), n1.Type(), missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
} else if ptr != 0 {
base.ErrorfAt(ncase.Pos, "impossible type switch case: %L cannot have dynamic type %v"+
" (%v method has pointer receiver)", n.Left.Right, n1.Type, missing.Sym)
base.ErrorfAt(ncase.Pos(), "impossible type switch case: %L cannot have dynamic type %v"+
" (%v method has pointer receiver)", n.Left().Right(), n1.Type(), missing.Sym)
} else {
base.ErrorfAt(ncase.Pos, "impossible type switch case: %L cannot have dynamic type %v"+
" (missing %v method)", n.Left.Right, n1.Type, missing.Sym)
base.ErrorfAt(ncase.Pos(), "impossible type switch case: %L cannot have dynamic type %v"+
" (missing %v method)", n.Left().Right(), n1.Type(), missing.Sym)
}
}
if n1.Op == ir.OTYPE {
ts.add(ncase.Pos, n1.Type)
if n1.Op() == ir.OTYPE {
ts.add(ncase.Pos(), n1.Type())
}
}
if ncase.Rlist.Len() != 0 {
if ncase.Rlist().Len() != 0 {
// Assign the clause variable's type.
vt := t
if len(ls) == 1 {
if ls[0].Op == ir.OTYPE {
vt = ls[0].Type
if ls[0].Op() == ir.OTYPE {
vt = ls[0].Type()
} else if !ir.IsNil(ls[0]) {
// Invalid single-type case;
// mark variable as broken.
@ -100,8 +100,8 @@ func typecheckTypeSwitch(n *ir.Node) {
}
}
nvar := ncase.Rlist.First()
nvar.Type = vt
nvar := ncase.Rlist().First()
nvar.SetType(vt)
if vt != nil {
nvar = typecheck(nvar, ctxExpr|ctxAssign)
} else {
@ -109,10 +109,10 @@ func typecheckTypeSwitch(n *ir.Node) {
nvar.SetTypecheck(1)
nvar.SetWalkdef(1)
}
ncase.Rlist.SetFirst(nvar)
ncase.Rlist().SetFirst(nvar)
}
typecheckslice(ncase.Nbody.Slice(), ctxStmt)
typecheckslice(ncase.Body().Slice(), ctxStmt)
}
}
@ -146,10 +146,10 @@ func (s *typeSet) add(pos src.XPos, typ *types.Type) {
func typecheckExprSwitch(n *ir.Node) {
t := types.Types[types.TBOOL]
if n.Left != nil {
n.Left = typecheck(n.Left, ctxExpr)
n.Left = defaultlit(n.Left, nil)
t = n.Left.Type
if n.Left() != nil {
n.SetLeft(typecheck(n.Left(), ctxExpr))
n.SetLeft(defaultlit(n.Left(), nil))
t = n.Left().Type()
}
var nilonly string
@ -164,9 +164,9 @@ func typecheckExprSwitch(n *ir.Node) {
case !IsComparable(t):
if t.IsStruct() {
base.ErrorfAt(n.Pos, "cannot switch on %L (struct containing %v cannot be compared)", n.Left, IncomparableField(t).Type)
base.ErrorfAt(n.Pos(), "cannot switch on %L (struct containing %v cannot be compared)", n.Left(), IncomparableField(t).Type)
} else {
base.ErrorfAt(n.Pos, "cannot switch on %L", n.Left)
base.ErrorfAt(n.Pos(), "cannot switch on %L", n.Left())
}
t = nil
}
@ -174,11 +174,11 @@ func typecheckExprSwitch(n *ir.Node) {
var defCase *ir.Node
var cs constSet
for _, ncase := range n.List.Slice() {
ls := ncase.List.Slice()
for _, ncase := range n.List().Slice() {
ls := ncase.List().Slice()
if len(ls) == 0 { // default:
if defCase != nil {
base.ErrorfAt(ncase.Pos, "multiple defaults in switch (first at %v)", ir.Line(defCase))
base.ErrorfAt(ncase.Pos(), "multiple defaults in switch (first at %v)", ir.Line(defCase))
} else {
defCase = ncase
}
@ -189,22 +189,22 @@ func typecheckExprSwitch(n *ir.Node) {
ls[i] = typecheck(ls[i], ctxExpr)
ls[i] = defaultlit(ls[i], t)
n1 := ls[i]
if t == nil || n1.Type == nil {
if t == nil || n1.Type() == nil {
continue
}
if nilonly != "" && !ir.IsNil(n1) {
base.ErrorfAt(ncase.Pos, "invalid case %v in switch (can only compare %s %v to nil)", n1, nilonly, n.Left)
} else if t.IsInterface() && !n1.Type.IsInterface() && !IsComparable(n1.Type) {
base.ErrorfAt(ncase.Pos, "invalid case %L in switch (incomparable type)", n1)
base.ErrorfAt(ncase.Pos(), "invalid case %v in switch (can only compare %s %v to nil)", n1, nilonly, n.Left())
} else if t.IsInterface() && !n1.Type().IsInterface() && !IsComparable(n1.Type()) {
base.ErrorfAt(ncase.Pos(), "invalid case %L in switch (incomparable type)", n1)
} else {
op1, _ := assignop(n1.Type, t)
op2, _ := assignop(t, n1.Type)
op1, _ := assignop(n1.Type(), t)
op2, _ := assignop(t, n1.Type())
if op1 == ir.OXXX && op2 == ir.OXXX {
if n.Left != nil {
base.ErrorfAt(ncase.Pos, "invalid case %v in switch on %v (mismatched types %v and %v)", n1, n.Left, n1.Type, t)
if n.Left() != nil {
base.ErrorfAt(ncase.Pos(), "invalid case %v in switch on %v (mismatched types %v and %v)", n1, n.Left(), n1.Type(), t)
} else {
base.ErrorfAt(ncase.Pos, "invalid case %v in switch (mismatched types %v and bool)", n1, n1.Type)
base.ErrorfAt(ncase.Pos(), "invalid case %v in switch (mismatched types %v and bool)", n1, n1.Type())
}
}
}
@ -215,23 +215,23 @@ func typecheckExprSwitch(n *ir.Node) {
// case GOARCH == "arm" && GOARM == "5":
// case GOARCH == "arm":
// which would both evaluate to false for non-ARM compiles.
if !n1.Type.IsBoolean() {
cs.add(ncase.Pos, n1, "case", "switch")
if !n1.Type().IsBoolean() {
cs.add(ncase.Pos(), n1, "case", "switch")
}
}
typecheckslice(ncase.Nbody.Slice(), ctxStmt)
typecheckslice(ncase.Body().Slice(), ctxStmt)
}
}
// walkswitch walks a switch statement.
func walkswitch(sw *ir.Node) {
// Guard against double walk, see #25776.
if sw.List.Len() == 0 && sw.Nbody.Len() > 0 {
if sw.List().Len() == 0 && sw.Body().Len() > 0 {
return // Was fatal, but eliminating every possible source of double-walking is hard
}
if sw.Left != nil && sw.Left.Op == ir.OTYPESW {
if sw.Left() != nil && sw.Left().Op() == ir.OTYPESW {
walkTypeSwitch(sw)
} else {
walkExprSwitch(sw)
@ -243,8 +243,8 @@ func walkswitch(sw *ir.Node) {
func walkExprSwitch(sw *ir.Node) {
lno := setlineno(sw)
cond := sw.Left
sw.Left = nil
cond := sw.Left()
sw.SetLeft(nil)
// convert switch {...} to switch true {...}
if cond == nil {
@ -260,13 +260,13 @@ func walkExprSwitch(sw *ir.Node) {
// because walkexpr will lower the string
// conversion into a runtime call.
// See issue 24937 for more discussion.
if cond.Op == ir.OBYTES2STR && allCaseExprsAreSideEffectFree(sw) {
cond.Op = ir.OBYTES2STRTMP
if cond.Op() == ir.OBYTES2STR && allCaseExprsAreSideEffectFree(sw) {
cond.SetOp(ir.OBYTES2STRTMP)
}
cond = walkexpr(cond, &sw.Ninit)
if cond.Op != ir.OLITERAL && cond.Op != ir.ONIL {
cond = copyexpr(cond, cond.Type, &sw.Nbody)
cond = walkexpr(cond, sw.PtrInit())
if cond.Op() != ir.OLITERAL && cond.Op() != ir.ONIL {
cond = copyexpr(cond, cond.Type(), sw.PtrBody())
}
base.Pos = lno
@ -277,43 +277,43 @@ func walkExprSwitch(sw *ir.Node) {
var defaultGoto *ir.Node
var body ir.Nodes
for _, ncase := range sw.List.Slice() {
for _, ncase := range sw.List().Slice() {
label := autolabel(".s")
jmp := npos(ncase.Pos, nodSym(ir.OGOTO, nil, label))
jmp := npos(ncase.Pos(), nodSym(ir.OGOTO, nil, label))
// Process case dispatch.
if ncase.List.Len() == 0 {
if ncase.List().Len() == 0 {
if defaultGoto != nil {
base.Fatalf("duplicate default case not detected during typechecking")
}
defaultGoto = jmp
}
for _, n1 := range ncase.List.Slice() {
s.Add(ncase.Pos, n1, jmp)
for _, n1 := range ncase.List().Slice() {
s.Add(ncase.Pos(), n1, jmp)
}
// Process body.
body.Append(npos(ncase.Pos, nodSym(ir.OLABEL, nil, label)))
body.Append(ncase.Nbody.Slice()...)
if fall, pos := hasFall(ncase.Nbody.Slice()); !fall {
body.Append(npos(ncase.Pos(), nodSym(ir.OLABEL, nil, label)))
body.Append(ncase.Body().Slice()...)
if fall, pos := hasFall(ncase.Body().Slice()); !fall {
br := ir.Nod(ir.OBREAK, nil, nil)
br.Pos = pos
br.SetPos(pos)
body.Append(br)
}
}
sw.List.Set(nil)
sw.PtrList().Set(nil)
if defaultGoto == nil {
br := ir.Nod(ir.OBREAK, nil, nil)
br.Pos = br.Pos.WithNotStmt()
br.SetPos(br.Pos().WithNotStmt())
defaultGoto = br
}
s.Emit(&sw.Nbody)
sw.Nbody.Append(defaultGoto)
sw.Nbody.AppendNodes(&body)
walkstmtlist(sw.Nbody.Slice())
s.Emit(sw.PtrBody())
sw.PtrBody().Append(defaultGoto)
sw.PtrBody().AppendNodes(&body)
walkstmtlist(sw.Body().Slice())
}
// An exprSwitch walks an expression switch.
@ -332,7 +332,7 @@ type exprClause struct {
func (s *exprSwitch) Add(pos src.XPos, expr, jmp *ir.Node) {
c := exprClause{pos: pos, lo: expr, hi: expr, jmp: jmp}
if okforcmp[s.exprname.Type.Etype] && expr.Op == ir.OLITERAL {
if okforcmp[s.exprname.Type().Etype] && expr.Op() == ir.OLITERAL {
s.clauses = append(s.clauses, c)
return
}
@ -359,7 +359,7 @@ func (s *exprSwitch) flush() {
// (e.g., sort.Slice doesn't need to invoke the less function
// when there's only a single slice element).
if s.exprname.Type.IsString() && len(cc) >= 2 {
if s.exprname.Type().IsString() && len(cc) >= 2 {
// Sort strings by length and then by value. It is
// much cheaper to compare lengths than values, and
// all we need here is consistency. We respect this
@ -395,8 +395,8 @@ func (s *exprSwitch) flush() {
},
func(i int, nif *ir.Node) {
run := runs[i]
nif.Left = ir.Nod(ir.OEQ, ir.Nod(ir.OLEN, s.exprname, nil), nodintconst(runLen(run)))
s.search(run, &nif.Nbody)
nif.SetLeft(ir.Nod(ir.OEQ, ir.Nod(ir.OLEN, s.exprname, nil), nodintconst(runLen(run))))
s.search(run, nif.PtrBody())
},
)
return
@ -407,7 +407,7 @@ func (s *exprSwitch) flush() {
})
// Merge consecutive integer cases.
if s.exprname.Type.IsInteger() {
if s.exprname.Type().IsInteger() {
merged := cc[:1]
for _, c := range cc[1:] {
last := &merged[len(merged)-1]
@ -430,8 +430,8 @@ func (s *exprSwitch) search(cc []exprClause, out *ir.Nodes) {
},
func(i int, nif *ir.Node) {
c := &cc[i]
nif.Left = c.test(s.exprname)
nif.Nbody.Set1(c.jmp)
nif.SetLeft(c.test(s.exprname))
nif.PtrBody().Set1(c.jmp)
},
)
}
@ -445,7 +445,7 @@ func (c *exprClause) test(exprname *ir.Node) *ir.Node {
}
// Optimize "switch true { ...}" and "switch false { ... }".
if ir.IsConst(exprname, constant.Bool) && !c.lo.Type.IsInterface() {
if ir.IsConst(exprname, constant.Bool) && !c.lo.Type().IsInterface() {
if exprname.BoolVal() {
return c.lo
} else {
@ -464,12 +464,12 @@ func allCaseExprsAreSideEffectFree(sw *ir.Node) bool {
// Restricting to constants is simple and probably powerful
// enough.
for _, ncase := range sw.List.Slice() {
if ncase.Op != ir.OCASE {
base.Fatalf("switch string(byteslice) bad op: %v", ncase.Op)
for _, ncase := range sw.List().Slice() {
if ncase.Op() != ir.OCASE {
base.Fatalf("switch string(byteslice) bad op: %v", ncase.Op())
}
for _, v := range ncase.List.Slice() {
if v.Op != ir.OLITERAL {
for _, v := range ncase.List().Slice() {
if v.Op() != ir.OLITERAL {
return false
}
}
@ -486,24 +486,24 @@ func hasFall(stmts []*ir.Node) (bool, src.XPos) {
// nodes will be at the end of the list.
i := len(stmts) - 1
for i >= 0 && stmts[i].Op == ir.OVARKILL {
for i >= 0 && stmts[i].Op() == ir.OVARKILL {
i--
}
if i < 0 {
return false, src.NoXPos
}
return stmts[i].Op == ir.OFALL, stmts[i].Pos
return stmts[i].Op() == ir.OFALL, stmts[i].Pos()
}
// walkTypeSwitch generates an AST that implements sw, where sw is a
// type switch.
func walkTypeSwitch(sw *ir.Node) {
var s typeSwitch
s.facename = sw.Left.Right
sw.Left = nil
s.facename = sw.Left().Right()
sw.SetLeft(nil)
s.facename = walkexpr(s.facename, &sw.Ninit)
s.facename = copyexpr(s.facename, s.facename.Type, &sw.Nbody)
s.facename = walkexpr(s.facename, sw.PtrInit())
s.facename = copyexpr(s.facename, s.facename.Type(), sw.PtrBody())
s.okname = temp(types.Types[types.TBOOL])
// Get interface descriptor word.
@ -518,54 +518,54 @@ func walkTypeSwitch(sw *ir.Node) {
// h := e._type.hash
// Use a similar strategy for non-empty interfaces.
ifNil := ir.Nod(ir.OIF, nil, nil)
ifNil.Left = ir.Nod(ir.OEQ, itab, nodnil())
ifNil.SetLeft(ir.Nod(ir.OEQ, itab, nodnil()))
base.Pos = base.Pos.WithNotStmt() // disable statement marks after the first check.
ifNil.Left = typecheck(ifNil.Left, ctxExpr)
ifNil.Left = defaultlit(ifNil.Left, nil)
ifNil.SetLeft(typecheck(ifNil.Left(), ctxExpr))
ifNil.SetLeft(defaultlit(ifNil.Left(), nil))
// ifNil.Nbody assigned at end.
sw.Nbody.Append(ifNil)
sw.PtrBody().Append(ifNil)
// Load hash from type or itab.
dotHash := nodSym(ir.ODOTPTR, itab, nil)
dotHash.Type = types.Types[types.TUINT32]
dotHash.SetType(types.Types[types.TUINT32])
dotHash.SetTypecheck(1)
if s.facename.Type.IsEmptyInterface() {
dotHash.Xoffset = int64(2 * Widthptr) // offset of hash in runtime._type
if s.facename.Type().IsEmptyInterface() {
dotHash.SetOffset(int64(2 * Widthptr)) // offset of hash in runtime._type
} else {
dotHash.Xoffset = int64(2 * Widthptr) // offset of hash in runtime.itab
dotHash.SetOffset(int64(2 * Widthptr)) // offset of hash in runtime.itab
}
dotHash.SetBounded(true) // guaranteed not to fault
s.hashname = copyexpr(dotHash, dotHash.Type, &sw.Nbody)
s.hashname = copyexpr(dotHash, dotHash.Type(), sw.PtrBody())
br := ir.Nod(ir.OBREAK, nil, nil)
var defaultGoto, nilGoto *ir.Node
var body ir.Nodes
for _, ncase := range sw.List.Slice() {
for _, ncase := range sw.List().Slice() {
var caseVar *ir.Node
if ncase.Rlist.Len() != 0 {
caseVar = ncase.Rlist.First()
if ncase.Rlist().Len() != 0 {
caseVar = ncase.Rlist().First()
}
// For single-type cases with an interface type,
// we initialize the case variable as part of the type assertion.
// In other cases, we initialize it in the body.
var singleType *types.Type
if ncase.List.Len() == 1 && ncase.List.First().Op == ir.OTYPE {
singleType = ncase.List.First().Type
if ncase.List().Len() == 1 && ncase.List().First().Op() == ir.OTYPE {
singleType = ncase.List().First().Type()
}
caseVarInitialized := false
label := autolabel(".s")
jmp := npos(ncase.Pos, nodSym(ir.OGOTO, nil, label))
jmp := npos(ncase.Pos(), nodSym(ir.OGOTO, nil, label))
if ncase.List.Len() == 0 { // default:
if ncase.List().Len() == 0 { // default:
if defaultGoto != nil {
base.Fatalf("duplicate default case not detected during typechecking")
}
defaultGoto = jmp
}
for _, n1 := range ncase.List.Slice() {
for _, n1 := range ncase.List().Slice() {
if ir.IsNil(n1) { // case nil:
if nilGoto != nil {
base.Fatalf("duplicate nil case not detected during typechecking")
@ -575,14 +575,14 @@ func walkTypeSwitch(sw *ir.Node) {
}
if singleType != nil && singleType.IsInterface() {
s.Add(ncase.Pos, n1.Type, caseVar, jmp)
s.Add(ncase.Pos(), n1.Type(), caseVar, jmp)
caseVarInitialized = true
} else {
s.Add(ncase.Pos, n1.Type, nil, jmp)
s.Add(ncase.Pos(), n1.Type(), nil, jmp)
}
}
body.Append(npos(ncase.Pos, nodSym(ir.OLABEL, nil, label)))
body.Append(npos(ncase.Pos(), nodSym(ir.OLABEL, nil, label)))
if caseVar != nil && !caseVarInitialized {
val := s.facename
if singleType != nil {
@ -590,19 +590,19 @@ func walkTypeSwitch(sw *ir.Node) {
if singleType.IsInterface() {
base.Fatalf("singleType interface should have been handled in Add")
}
val = ifaceData(ncase.Pos, s.facename, singleType)
val = ifaceData(ncase.Pos(), s.facename, singleType)
}
l := []*ir.Node{
ir.NodAt(ncase.Pos, ir.ODCL, caseVar, nil),
ir.NodAt(ncase.Pos, ir.OAS, caseVar, val),
ir.NodAt(ncase.Pos(), ir.ODCL, caseVar, nil),
ir.NodAt(ncase.Pos(), ir.OAS, caseVar, val),
}
typecheckslice(l, ctxStmt)
body.Append(l...)
}
body.Append(ncase.Nbody.Slice()...)
body.Append(ncase.Body().Slice()...)
body.Append(br)
}
sw.List.Set(nil)
sw.PtrList().Set(nil)
if defaultGoto == nil {
defaultGoto = br
@ -610,13 +610,13 @@ func walkTypeSwitch(sw *ir.Node) {
if nilGoto == nil {
nilGoto = defaultGoto
}
ifNil.Nbody.Set1(nilGoto)
ifNil.PtrBody().Set1(nilGoto)
s.Emit(&sw.Nbody)
sw.Nbody.Append(defaultGoto)
sw.Nbody.AppendNodes(&body)
s.Emit(sw.PtrBody())
sw.PtrBody().Append(defaultGoto)
sw.PtrBody().AppendNodes(&body)
walkstmtlist(sw.Nbody.Slice())
walkstmtlist(sw.Body().Slice())
}
// A typeSwitch walks a type switch.
@ -650,18 +650,18 @@ func (s *typeSwitch) Add(pos src.XPos, typ *types.Type, caseVar, jmp *ir.Node) {
// cv, ok = iface.(type)
as := ir.NodAt(pos, ir.OAS2, nil, nil)
as.List.Set2(caseVar, s.okname) // cv, ok =
as.PtrList().Set2(caseVar, s.okname) // cv, ok =
dot := ir.NodAt(pos, ir.ODOTTYPE, s.facename, nil)
dot.Type = typ // iface.(type)
as.Rlist.Set1(dot)
dot.SetType(typ) // iface.(type)
as.PtrRlist().Set1(dot)
as = typecheck(as, ctxStmt)
as = walkexpr(as, &body)
body.Append(as)
// if ok { goto label }
nif := ir.NodAt(pos, ir.OIF, nil, nil)
nif.Left = s.okname
nif.Nbody.Set1(jmp)
nif.SetLeft(s.okname)
nif.PtrBody().Set1(jmp)
body.Append(nif)
if !typ.IsInterface() {
@ -710,8 +710,8 @@ func (s *typeSwitch) flush() {
// TODO(mdempsky): Omit hash equality check if
// there's only one type.
c := cc[i]
nif.Left = ir.Nod(ir.OEQ, s.hashname, nodintconst(int64(c.hash)))
nif.Nbody.AppendNodes(&c.body)
nif.SetLeft(ir.Nod(ir.OEQ, s.hashname, nodintconst(int64(c.hash))))
nif.PtrBody().AppendNodes(&c.body)
},
)
}
@ -736,22 +736,22 @@ func binarySearch(n int, out *ir.Nodes, less func(i int) *ir.Node, leaf func(i i
nif := ir.Nod(ir.OIF, nil, nil)
leaf(i, nif)
base.Pos = base.Pos.WithNotStmt()
nif.Left = typecheck(nif.Left, ctxExpr)
nif.Left = defaultlit(nif.Left, nil)
nif.SetLeft(typecheck(nif.Left(), ctxExpr))
nif.SetLeft(defaultlit(nif.Left(), nil))
out.Append(nif)
out = &nif.Rlist
out = nif.PtrRlist()
}
return
}
half := lo + n/2
nif := ir.Nod(ir.OIF, nil, nil)
nif.Left = less(half)
nif.SetLeft(less(half))
base.Pos = base.Pos.WithNotStmt()
nif.Left = typecheck(nif.Left, ctxExpr)
nif.Left = defaultlit(nif.Left, nil)
do(lo, half, &nif.Nbody)
do(half, hi, &nif.Rlist)
nif.SetLeft(typecheck(nif.Left(), ctxExpr))
nif.SetLeft(defaultlit(nif.Left(), nil))
do(lo, half, nif.PtrBody())
do(half, hi, nif.PtrRlist())
out.Append(nif)
}