func ssaType(i ssa.Instruction, out *bytes.Buffer) { switch i := i.(type) { case *ssa.Alloc: out.WriteString(" *ssa.Alloc ") out.WriteString(" Comment: " + i.Comment + " Heap: ") if i.Heap { out.WriteString(" true \n") } else { out.WriteString(" false \n") } case *ssa.BinOp: out.WriteString(" *ssa.BinOp ") out.WriteString(" Op: " + i.Op.String() + " X: " + i.X.String() + " Y: " + i.Y.String() + "\n") /* case *ssa.Builtin: out.WriteString("*ssa.Builtin \n") */ case *ssa.ChangeInterface: out.WriteString(" *ssa.ChangeInterface ") out.WriteString(" X: " + i.X.String() + "\n") case *ssa.ChangeType: out.WriteString(" *ssa.ChangeType ") out.WriteString(" X: " + i.X.String() + "\n") /* case *ssa.Const: out.WriteString("*ssa.Const ") out.WriteString("Value: " + i.Value.String() + "\n") */ case *ssa.Convert: out.WriteString(" ssa.Convert ") out.WriteString(" X: " + i.X.String() + "\n") case *ssa.Extract: out.WriteString(" ssa.Extract") out.WriteString(" Tuple: " + i.Tuple.String() + " Index ") out.WriteString(strconv.Itoa(i.Index)) case *ssa.Field: out.WriteString(" ssa.Field") out.WriteString(" X: " + i.X.String() + " Field " + strconv.Itoa(i.Field) + "\n") case *ssa.FieldAddr: out.WriteString(" ssa.FieldAddr") out.WriteString(" X: " + i.X.String() + " Field " + strconv.Itoa(i.Field) + "\n") /* case *ssa.FreeVar: out.WriteString("ssa.FreeVar") */ /* case *ssa.Global: out.WriteString("*ssa.Global") out.WriteString("Pkg " + i.Pkg.String() + "\n") */ case *ssa.Index: out.WriteString(" *ssa.Index ") out.WriteString(" X: " + i.X.String() + " Index " + i.Index.String() + " \n") case *ssa.IndexAddr: out.WriteString(" *ssa.IndexAddr") out.WriteString(" X: " + i.X.String() + " Index " + i.Index.String() + "\n") case *ssa.Lookup: out.WriteString(" *ssa.LookUp") out.WriteString(" x: " + i.X.String() + " Index " + i.Index.String() + " CommaOk " + strconv.FormatBool(i.CommaOk) + "\n") case *ssa.MakeChan: out.WriteString(" *ssa.MakeChan") out.WriteString(" Size: " + i.Size.String() + "\n") case *ssa.MakeClosure: out.WriteString(" *ssa.MakeClosure") out.WriteString(" FN: " + i.Fn.String() + " Bindings ") for _, i := range i.Bindings { out.WriteString(" " + i.String() + " ") } out.WriteString("\n") case *ssa.MakeInterface: out.WriteString(" *ssa.MakeInterface") out.WriteString(" X: " + i.X.String() + "\n") case *ssa.MakeMap: out.WriteString(" *ssa.MakeMap") if i.Reserve != nil { out.WriteString(" Reserve: " + i.Reserve.String() + "\n") } case *ssa.MakeSlice: out.WriteString(" *ssa.MakeSlice") out.WriteString(" Len: " + i.Len.String() + " Cap : " + i.Cap.String() + " \n") case *ssa.Next: out.WriteString(" *ssa.Next") out.WriteString(" Iter " + i.Iter.String() + " isString " + strconv.FormatBool(i.IsString) + "\n") /* case *ssa.Parameter: out.WriteString("*ssa.Parameter") */ case *ssa.Phi: out.WriteString(" *ssa.Phi") out.WriteString(" Comment: " + i.Comment + " Edges ") for _, i := range i.Edges { out.WriteString(" " + i.String() + " ") } out.WriteString(" \n") case *ssa.Range: out.WriteString(" *ssa.Range") out.WriteString(" X " + i.X.String() + "\n") case *ssa.Select: out.WriteString(" *ssa.Select") out.WriteString(" States: ") for _, i := range i.States { out.WriteString(" Channel: " + i.Chan.String() + " Send : " + i.Send.String()) } out.WriteString(" Blocking: " + strconv.FormatBool(i.Blocking) + "\n") case *ssa.Send: out.WriteString(" *ssa.Send") out.WriteString(" Chan: " + i.Chan.String() + " X: " + i.X.String() + "\n") case *ssa.Slice: out.WriteString(" *ssa.Slice") if i.X != nil { out.WriteString(" x: " + i.X.String()) } if i.Low != nil { out.WriteString(" Low: " + i.Low.String()) } if i.Max != nil { out.WriteString(" Max: " + i.Max.String()) } out.WriteString("\n") case *ssa.Store: out.WriteString(" *ssa.Store") out.WriteString(" Addr: " + i.Addr.String() + " Val " + i.Addr.String() + "\n") case *ssa.TypeAssert: out.WriteString(" *ssa.TypeAssert") out.WriteString(" X: " + i.X.String() + " AssertedType: " + i.AssertedType.String() + " CommaOk " + strconv.FormatBool(i.CommaOk) + "\n") case *ssa.UnOp: out.WriteString(" *ssa.UnoOp") out.WriteString(" Op: " + i.Op.String() + " X: " + i.X.String() + " CommaOk: " + strconv.FormatBool(i.CommaOk) + "\n") } }
func visitInst(inst ssa.Instruction, fr *frame) { switch inst := inst.(type) { case *ssa.MakeChan: visitMakeChan(inst, fr) case *ssa.Send: visitSend(inst, fr) case *ssa.UnOp: switch inst.Op { case token.ARROW: visitRecv(inst, fr) case token.MUL: visitDeref(inst, fr) default: fmt.Fprintf(os.Stderr, " # unhandled %s = %s\n", red(inst.Name()), red(inst.String())) } case *ssa.Call: visitCall(inst, fr) case *ssa.Extract: visitExtract(inst, fr) case *ssa.Go: fr.callGo(inst) case *ssa.Return: fr.retvals = visitReturn(inst, fr) case *ssa.Store: visitStore(inst, fr) case *ssa.Alloc: visitAlloc(inst, fr) case *ssa.MakeClosure: visitMakeClosure(inst, fr) case *ssa.Select: visitSelect(inst, fr) case *ssa.ChangeType: visitChangeType(inst, fr) case *ssa.ChangeInterface: visitChangeInterface(inst, fr) case *ssa.If: visitIf(inst, fr) case *ssa.Jump: visitJump(inst, fr) case *ssa.BinOp: visitBinOp(inst, fr) case *ssa.Slice: visitSlice(inst, fr) case *ssa.MakeSlice: visitMakeSlice(inst, fr) case *ssa.FieldAddr: visitFieldAddr(inst, fr) case *ssa.Field: visitField(inst, fr) case *ssa.IndexAddr: visitIndexAddr(inst, fr) case *ssa.Index: visitIndex(inst, fr) case *ssa.Defer: visitDefer(inst, fr) case *ssa.RunDefers: visitRunDefers(inst, fr) case *ssa.Phi: visitPhi(inst, fr) case *ssa.TypeAssert: visitTypeAssert(inst, fr) case *ssa.MakeInterface: visitMakeInterface(inst, fr) case *ssa.DebugRef: default: // Everything else not handled yet if v, ok := inst.(ssa.Value); ok { fmt.Fprintf(os.Stderr, " # unhandled %s = %s\n", red(v.Name()), red(v.String())) } else { fmt.Fprintf(os.Stderr, " # unhandled %s\n", red(inst.String())) } } }