Exemplo n.º 1
0
func visitRecv(recv *ssa.UnOp, fr *frame) {
	locn := loc(fr, recv.X.Pos())
	if vd, kind := fr.get(recv.X); kind == Chan {
		ch := fr.env.chans[vd]
		if recv.CommaOk {
			// ReceiveOK test
			fr.recvok[recv] = ch
			// TODO(nickng) technically this should do receive (both branches)
		} else {
			// Normal receive
			fr.gortn.AddNode(sesstype.NewRecvNode(*ch, fr.gortn.role, recv.X.Type()))
			fmt.Fprintf(os.Stderr, "  %s\n", orange((*fr.gortn.leaf).String()))
		}
	} else if kind == Nothing {
		fr.locals[recv.X] = utils.NewDef(recv.X)
		ch := fr.env.session.MakeExtChan(fr.locals[recv.X], fr.gortn.role)
		fr.env.chans[fr.locals[recv.X]] = &ch
		fr.gortn.AddNode(sesstype.NewRecvNode(ch, fr.gortn.role, recv.X.Type()))
		fmt.Fprintf(os.Stderr, "  %s\n", orange((*fr.gortn.leaf).String()))
		fmt.Fprintf(os.Stderr, "   ^ Recv: Channel %s at %s is external\n", reg(recv.X), locn)
	} else {
		fr.printCallStack()
		panic(fmt.Sprintf("Recv: Channel %s at %s is of wrong kind", reg(recv.X), locn))
	}
}
Exemplo n.º 2
0
func visitIf(inst *ssa.If, fr *frame) {
	if len(inst.Block().Succs) != 2 {
		panic("If: Cannot handle If with more or less than 2 successor blocks!")
	}

	ifparent := fr.gortn.leaf
	if ifparent == nil {
		panic("If: Parent is nil")
	}

	if ch, isRecvTest := fr.env.recvTest[inst.Cond]; isRecvTest {
		fmt.Fprintf(os.Stderr, "  @ Switch to recvtest true\n")
		fr.gortn.leaf = ifparent
		fr.gortn.AddNode(sesstype.NewRecvNode(*ch, fr.gortn.role, ch.Type()))
		fmt.Fprintf(os.Stderr, "  %s\n", orange((*fr.gortn.leaf).String()))
		visitBlock(inst.Block().Succs[0], fr)

		fmt.Fprintf(os.Stderr, "  @ Switch to recvtest false\n")
		fr.gortn.leaf = ifparent
		fr.gortn.AddNode(sesstype.NewRecvStopNode(*ch, fr.gortn.role, ch.Type()))
		fmt.Fprintf(os.Stderr, "  %s\n", orange((*fr.gortn.leaf).String()))
		visitBlock(inst.Block().Succs[1], fr)
	} else if selTest, isSelTest := fr.env.selTest[inst.Cond]; isSelTest {
		// Check if this is a select-test-jump, if so handle separately.
		fmt.Fprintf(os.Stderr, "  @ Switch to select branch #%d\n", selTest.idx)
		if selParent, ok := fr.env.selNode[selTest.tpl]; ok {
			fr.gortn.leaf = ifparent
			*fr.gortn.leaf = (*selParent.parent).Child(selTest.idx)
			visitBlock(inst.Block().Succs[0], fr)

			if !selParent.blocking && len((*selParent.parent).Children()) > selTest.idx+1 {
				*fr.gortn.leaf = (*selParent.parent).Child(selTest.idx + 1)
			}
			visitBlock(inst.Block().Succs[1], fr)
		} else {
			panic("Select without corresponding sesstype.Node")
		}
	} else {
		fr.env.ifparent.Push(*fr.gortn.leaf)

		parent := fr.env.ifparent.Top()
		fr.gortn.leaf = &parent
		fr.gortn.AddNode(&sesstype.EmptyBodyNode{})
		visitBlock(inst.Block().Succs[0], fr)

		parent = fr.env.ifparent.Top()
		fr.gortn.leaf = &parent
		fr.gortn.AddNode(&sesstype.EmptyBodyNode{})
		visitBlock(inst.Block().Succs[1], fr)

		fr.env.ifparent.Pop()
	}
	// This is end of the block so no continuation
}