// chanOps returns a slice of all the channel operations in the instruction. // Derived from cmd/guru/peers.go. func chanOps(instr ssa.Instruction) []chanOp { fn := instr.Parent() var ops []chanOp switch instr := instr.(type) { case *ssa.UnOp: if instr.Op == token.ARROW { // TODO(adonovan): don't assume <-ch; could be 'range ch'. ops = append(ops, chanOp{instr.X, "received", instr.Pos(), len("<-"), fn}) } case *ssa.Send: ops = append(ops, chanOp{instr.Chan, "sent", instr.Pos(), len("<-"), fn}) case *ssa.Select: for _, st := range instr.States { mode := "received" if st.Dir == types.SendOnly { mode = "sent" } ops = append(ops, chanOp{st.Chan, mode, st.Pos, len("<-"), fn}) } case ssa.CallInstruction: call := instr.Common() if blt, ok := call.Value.(*ssa.Builtin); ok && blt.Name() == "close" { pos := instr.Common().Pos() ops = append(ops, chanOp{call.Args[0], "closed", pos - token.Pos(len("close")), len("close("), fn}) } } return ops }
// chanOps extract all channel operations from an instruction. func chanOps(instr ssa.Instruction) []ChanOp { var ops []ChanOp switch instr := instr.(type) { case *ssa.Send: ops = append(ops, ChanOp{instr.Chan, ChanSend, instr.Pos()}) case *ssa.UnOp: if instr.Op == token.ARROW { ops = append(ops, ChanOp{instr.X, ChanRecv, instr.Pos()}) } case *ssa.Select: for _, st := range instr.States { switch st.Dir { case types.SendOnly: ops = append(ops, ChanOp{st.Chan, ChanSend, st.Pos}) case types.RecvOnly: ops = append(ops, ChanOp{st.Chan, ChanRecv, st.Pos}) } } case ssa.CallInstruction: common := instr.Common() if b, ok := common.Value.(*ssa.Builtin); ok && b.Name() == "close" { ops = append(ops, ChanOp{common.Args[0], ChanClose, common.Pos()}) } } return ops }
// chanOps returns a slice of all the channel operations in the instruction. func chanOps(instr ssa.Instruction) []chanOp { // TODO(adonovan): handle calls to reflect.{Select,Recv,Send,Close} too. var ops []chanOp switch instr := instr.(type) { case *ssa.UnOp: if instr.Op == token.ARROW { ops = append(ops, chanOp{instr.X, types.RecvOnly, instr.Pos()}) } case *ssa.Send: ops = append(ops, chanOp{instr.Chan, types.SendOnly, instr.Pos()}) case *ssa.Select: for _, st := range instr.States { ops = append(ops, chanOp{st.Chan, st.Dir, st.Pos}) } case ssa.CallInstruction: cc := instr.Common() if b, ok := cc.Value.(*ssa.Builtin); ok && b.Name() == "close" { ops = append(ops, chanOp{cc.Args[0], types.SendRecv, cc.Pos()}) } } return ops }