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)) } }
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 }