Example #1
0
// 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
}
Example #2
0
// 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
}
Example #3
0
// 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
}