diff options
Diffstat (limited to 'src/cmd/compile/internal/gc/select.go')
-rw-r--r-- | src/cmd/compile/internal/gc/select.go | 144 |
1 files changed, 31 insertions, 113 deletions
diff --git a/src/cmd/compile/internal/gc/select.go b/src/cmd/compile/internal/gc/select.go index 67a2cfd312..51bb1e5355 100644 --- a/src/cmd/compile/internal/gc/select.go +++ b/src/cmd/compile/internal/gc/select.go @@ -7,92 +7,10 @@ package gc import ( "cmd/compile/internal/base" "cmd/compile/internal/ir" + "cmd/compile/internal/typecheck" "cmd/compile/internal/types" ) -// select -func typecheckselect(sel *ir.SelectStmt) { - var def ir.Node - lno := ir.SetPos(sel) - typecheckslice(sel.Init(), ctxStmt) - for _, ncase := range sel.Cases { - ncase := ncase.(*ir.CaseStmt) - - if len(ncase.List) == 0 { - // default - if def != nil { - base.ErrorfAt(ncase.Pos(), "multiple defaults in select (first at %v)", ir.Line(def)) - } else { - def = ncase - } - } else if len(ncase.List) > 1 { - base.ErrorfAt(ncase.Pos(), "select cases cannot be lists") - } else { - ncase.List[0] = typecheck(ncase.List[0], ctxStmt) - n := ncase.List[0] - ncase.Comm = n - ncase.List.Set(nil) - oselrecv2 := func(dst, recv ir.Node, colas bool) { - n := ir.NewAssignListStmt(n.Pos(), ir.OSELRECV2, nil, nil) - n.Lhs = []ir.Node{dst, ir.BlankNode} - n.Rhs = []ir.Node{recv} - n.Def = colas - n.SetTypecheck(1) - ncase.Comm = n - } - switch n.Op() { - default: - pos := n.Pos() - if n.Op() == ir.ONAME { - // We don't have the right position for ONAME nodes (see #15459 and - // others). Using ncase.Pos for now as it will provide the correct - // line number (assuming the expression follows the "case" keyword - // on the same line). This matches the approach before 1.10. - pos = ncase.Pos() - } - base.ErrorfAt(pos, "select case must be receive, send or assign recv") - - case ir.OAS: - // convert x = <-c into x, _ = <-c - // remove implicit conversions; the eventual assignment - // will reintroduce them. - n := n.(*ir.AssignStmt) - if r := n.Y; r.Op() == ir.OCONVNOP || r.Op() == ir.OCONVIFACE { - r := r.(*ir.ConvExpr) - if r.Implicit() { - n.Y = r.X - } - } - if n.Y.Op() != ir.ORECV { - base.ErrorfAt(n.Pos(), "select assignment must have receive on right hand side") - break - } - oselrecv2(n.X, n.Y, n.Def) - - case ir.OAS2RECV: - n := n.(*ir.AssignListStmt) - if n.Rhs[0].Op() != ir.ORECV { - base.ErrorfAt(n.Pos(), "select assignment must have receive on right hand side") - break - } - n.SetOp(ir.OSELRECV2) - - case ir.ORECV: - // convert <-c into _, _ = <-c - n := n.(*ir.UnaryExpr) - oselrecv2(ir.BlankNode, n, false) - - case ir.OSEND: - break - } - } - - typecheckslice(ncase.Body, ctxStmt) - } - - base.Pos = lno -} - func walkselect(sel *ir.SelectStmt) { lno := ir.SetPos(sel) if len(sel.Compiled) != 0 { @@ -167,14 +85,14 @@ func walkselectcases(cases ir.Nodes) []ir.Node { switch n.Op() { case ir.OSEND: n := n.(*ir.SendStmt) - n.Value = nodAddr(n.Value) - n.Value = typecheck(n.Value, ctxExpr) + n.Value = typecheck.NodAddr(n.Value) + n.Value = typecheck.Expr(n.Value) case ir.OSELRECV2: n := n.(*ir.AssignListStmt) if !ir.IsBlank(n.Lhs[0]) { - n.Lhs[0] = nodAddr(n.Lhs[0]) - n.Lhs[0] = typecheck(n.Lhs[0], ctxExpr) + n.Lhs[0] = typecheck.NodAddr(n.Lhs[0]) + n.Lhs[0] = typecheck.Expr(n.Lhs[0]) } } } @@ -207,7 +125,7 @@ func walkselectcases(cases ir.Nodes) []ir.Node { ch := recv.X elem := n.Lhs[0] if ir.IsBlank(elem) { - elem = nodnil() + elem = typecheck.NodNil() } if ir.IsBlank(n.Lhs[1]) { // if selectnbrecv(&v, c) { body } else { default body } @@ -215,12 +133,12 @@ func walkselectcases(cases ir.Nodes) []ir.Node { } else { // TODO(cuonglm): make this use selectnbrecv() // if selectnbrecv2(&v, &received, c) { body } else { default body } - receivedp := typecheck(nodAddr(n.Lhs[1]), ctxExpr) + receivedp := typecheck.Expr(typecheck.NodAddr(n.Lhs[1])) call = mkcall1(chanfn("selectnbrecv2", 2, ch.Type()), types.Types[types.TBOOL], r.PtrInit(), elem, receivedp, ch) } } - r.Cond = typecheck(call, ctxExpr) + r.Cond = typecheck.Expr(call) r.Body.Set(cas.Body) r.Else.Set(append(dflt.Init(), dflt.Body...)) return []ir.Node{r, ir.NewBranchStmt(base.Pos, ir.OBREAK, nil)} @@ -236,18 +154,18 @@ func walkselectcases(cases ir.Nodes) []ir.Node { // generate sel-struct base.Pos = sellineno - selv := temp(types.NewArray(scasetype(), int64(ncas))) - init = append(init, typecheck(ir.NewAssignStmt(base.Pos, selv, nil), ctxStmt)) + selv := typecheck.Temp(types.NewArray(scasetype(), int64(ncas))) + init = append(init, typecheck.Stmt(ir.NewAssignStmt(base.Pos, selv, nil))) // No initialization for order; runtime.selectgo is responsible for that. - order := temp(types.NewArray(types.Types[types.TUINT16], 2*int64(ncas))) + order := typecheck.Temp(types.NewArray(types.Types[types.TUINT16], 2*int64(ncas))) var pc0, pcs ir.Node if base.Flag.Race { - pcs = temp(types.NewArray(types.Types[types.TUINTPTR], int64(ncas))) - pc0 = typecheck(nodAddr(ir.NewIndexExpr(base.Pos, pcs, ir.NewInt(0))), ctxExpr) + pcs = typecheck.Temp(types.NewArray(types.Types[types.TUINTPTR], int64(ncas))) + pc0 = typecheck.Expr(typecheck.NodAddr(ir.NewIndexExpr(base.Pos, pcs, ir.NewInt(0)))) } else { - pc0 = nodnil() + pc0 = typecheck.NodNil() } // register cases @@ -286,21 +204,21 @@ func walkselectcases(cases ir.Nodes) []ir.Node { casorder[i] = cas setField := func(f string, val ir.Node) { - r := ir.NewAssignStmt(base.Pos, ir.NewSelectorExpr(base.Pos, ir.ODOT, ir.NewIndexExpr(base.Pos, selv, ir.NewInt(int64(i))), lookup(f)), val) - init = append(init, typecheck(r, ctxStmt)) + r := ir.NewAssignStmt(base.Pos, ir.NewSelectorExpr(base.Pos, ir.ODOT, ir.NewIndexExpr(base.Pos, selv, ir.NewInt(int64(i))), typecheck.Lookup(f)), val) + init = append(init, typecheck.Stmt(r)) } - c = convnop(c, types.Types[types.TUNSAFEPTR]) + c = typecheck.ConvNop(c, types.Types[types.TUNSAFEPTR]) setField("c", c) if !ir.IsBlank(elem) { - elem = convnop(elem, types.Types[types.TUNSAFEPTR]) + elem = typecheck.ConvNop(elem, types.Types[types.TUNSAFEPTR]) setField("elem", elem) } // TODO(mdempsky): There should be a cleaner way to // handle this. if base.Flag.Race { - r := mkcall("selectsetpc", nil, nil, nodAddr(ir.NewIndexExpr(base.Pos, pcs, ir.NewInt(int64(i))))) + r := mkcall("selectsetpc", nil, nil, typecheck.NodAddr(ir.NewIndexExpr(base.Pos, pcs, ir.NewInt(int64(i))))) init = append(init, r) } } @@ -310,13 +228,13 @@ func walkselectcases(cases ir.Nodes) []ir.Node { // run the select base.Pos = sellineno - chosen := temp(types.Types[types.TINT]) - recvOK := temp(types.Types[types.TBOOL]) + chosen := typecheck.Temp(types.Types[types.TINT]) + recvOK := typecheck.Temp(types.Types[types.TBOOL]) r := ir.NewAssignListStmt(base.Pos, ir.OAS2, nil, nil) r.Lhs = []ir.Node{chosen, recvOK} - fn := syslook("selectgo") + fn := typecheck.LookupRuntime("selectgo") r.Rhs = []ir.Node{mkcall1(fn, fn.Type().Results(), nil, bytePtrToIndex(selv, 0), bytePtrToIndex(order, 0), pc0, ir.NewInt(int64(nsends)), ir.NewInt(int64(nrecvs)), ir.NewBool(dflt == nil))} - init = append(init, typecheck(r, ctxStmt)) + init = append(init, typecheck.Stmt(r)) // selv and order are no longer alive after selectgo. init = append(init, ir.NewUnaryExpr(base.Pos, ir.OVARKILL, selv)) @@ -327,8 +245,8 @@ func walkselectcases(cases ir.Nodes) []ir.Node { // dispatch cases dispatch := func(cond ir.Node, cas *ir.CaseStmt) { - cond = typecheck(cond, ctxExpr) - cond = defaultlit(cond, nil) + cond = typecheck.Expr(cond) + cond = typecheck.DefaultLit(cond, nil) r := ir.NewIfStmt(base.Pos, cond, nil, nil) @@ -336,7 +254,7 @@ func walkselectcases(cases ir.Nodes) []ir.Node { n := n.(*ir.AssignListStmt) if !ir.IsBlank(n.Lhs[1]) { x := ir.NewAssignStmt(base.Pos, n.Lhs[1], recvOK) - r.Body.Append(typecheck(x, ctxStmt)) + r.Body.Append(typecheck.Stmt(x)) } } @@ -359,9 +277,9 @@ func walkselectcases(cases ir.Nodes) []ir.Node { // bytePtrToIndex returns a Node representing "(*byte)(&n[i])". func bytePtrToIndex(n ir.Node, i int64) ir.Node { - s := nodAddr(ir.NewIndexExpr(base.Pos, n, ir.NewInt(i))) + s := typecheck.NodAddr(ir.NewIndexExpr(base.Pos, n, ir.NewInt(i))) t := types.NewPtr(types.Types[types.TUINT8]) - return convnop(s, t) + return typecheck.ConvNop(s, t) } var scase *types.Type @@ -369,9 +287,9 @@ var scase *types.Type // Keep in sync with src/runtime/select.go. func scasetype() *types.Type { if scase == nil { - scase = tostruct([]*ir.Field{ - ir.NewField(base.Pos, lookup("c"), nil, types.Types[types.TUNSAFEPTR]), - ir.NewField(base.Pos, lookup("elem"), nil, types.Types[types.TUNSAFEPTR]), + scase = typecheck.NewStructType([]*ir.Field{ + ir.NewField(base.Pos, typecheck.Lookup("c"), nil, types.Types[types.TUNSAFEPTR]), + ir.NewField(base.Pos, typecheck.Lookup("elem"), nil, types.Types[types.TUNSAFEPTR]), }) scase.SetNoalg(true) } |