// prepareCall determines the function value and argument values for a // function call in a Call, Go or Defer instruction, peforming // interface method lookup if needed. // func prepareCall(fr *frame, call *ssa.CallCommon) (fn value, args []value) { if call.Func != nil { // Function call. fn = fr.get(call.Func) } else { // Interface method invocation. recv := fr.get(call.Recv).(iface) if recv.t == nil { panic("method invoked on nil interface") } id := call.MethodId() m := findMethodSet(fr.i, recv.t)[id] if m == nil { // Unreachable in well-typed programs. panic(fmt.Sprintf("method set for dynamic type %v does not contain %s", recv.t, id)) } _, aptr := recv.v.(*value) // actual pointerness _, fptr := m.Signature.Recv().Type().(*types.Pointer) // formal pointerness switch { case aptr == fptr: args = append(args, copyVal(recv.v)) case aptr: // Calling func(T) with a *T receiver: make a copy. args = append(args, copyVal(*recv.v.(*value))) case fptr: panic("illegal call of *T method with T receiver") } fn = m } for _, arg := range call.Args { args = append(args, fr.get(arg)) } return }