func emitConv(f *Function, val Value, typ types.Type) Value {
	t_src := val.Type()
	if types.Identical(t_src, typ) {
		return val
	}
	ut_dst := typ.Underlying()
	ut_src := t_src.Underlying()
	if isValuePreserving(ut_src, ut_dst) {
		c := &ChangeType{X: val}
		c.setType(typ)
		return f.emit(c)
	}
	if _, ok := ut_dst.(*types.Interface); ok {
		if _, ok := ut_src.(*types.Interface); ok {
			c := &ChangeInterface{X: val}
			c.setType(typ)
			return f.emit(c)
		}
		if ut_src == tUntypedNil {
			return nilConst(typ)
		}
		if t, ok := ut_src.(*types.Basic); ok && t.Info()&types.IsUntyped != 0 {
			val = emitConv(f, val, DefaultType(ut_src))
		}
		f.Pkg.Prog.needMethodsOf(val.Type())
		mi := &MakeInterface{X: val}
		mi.setType(typ)
		return f.emit(mi)
	}
	if c, ok := val.(*Const); ok {
		if _, ok := ut_dst.(*types.Basic); ok || c.IsNil() {
			return NewConst(c.Value, typ)
		}
	}
	_, ok1 := ut_src.(*types.Basic)
	_, ok2 := ut_dst.(*types.Basic)
	if ok1 || ok2 {
		c := &Convert{X: val}
		c.setType(typ)
		return f.emit(c)
	}
	panic(fmt.Sprintf("in %s: cannot convert %s (%s) to %s", f, val, val.Type(), typ))
}
emitConv emits to f code to convert Value val to exactly type typ,
and returns the converted value.  Implicit conversions are required
by language assignability rules in assignments, parameter passing,
etc.  Conversions cannot fail dynamically.
package ssa
import (
	"fmt"
	"go/ast"
	"go/token"
	"go/types"
)
func emitNew(f *Function, typ types.Type, pos token.Pos) *Alloc {
	v := &Alloc{Heap: true}
	v.setType(types.NewPointer(typ))
	v.setPos(pos)
	f.emit(v)
	return v
}
func emitLoad(f *Function, addr Value) *UnOp {
	v := &UnOp{Op: token.MUL, X: addr}
	v.setType(deref(addr.Type()))
	f.emit(v)
	return v
}
func emitDebugRef(f *Function, e ast.Expr, v Value, isAddr bool) {
	if !f.debugInfo() {
		return  
	}
	if v == nil || e == nil {
		panic("nil")
	}
	var obj types.Object
	e = unparen(e)
	if id, ok := e.(*ast.Ident); ok {
		if isBlankIdent(id) {
			return
		}
		obj = f.Pkg.objectOf(id)
		switch obj.(type) {
		case *types.Nil, *types.Const, *types.Builtin:
			return
		}
	}
	f.emit(&DebugRef{
		X:      v,
		Expr:   e,
		IsAddr: isAddr,
		object: obj,
	})
}
func emitArith(f *Function, op token.Token, x, y Value, t types.Type, pos token.Pos) Value {
	switch op {
	case token.SHL, token.SHR:
		x = emitConv(f, x, t)
		if b, ok := y.Type().Underlying().(*types.Basic); ok && b.Info()&types.IsUnsigned == 0 {
			y = emitConv(f, y, types.Typ[types.Uint64])
		}
	case token.ADD, token.SUB, token.MUL, token.QUO, token.REM, token.AND, token.OR, token.XOR, token.AND_NOT:
		x = emitConv(f, x, t)
		y = emitConv(f, y, t)
	default:
		panic("illegal op in emitArith: " + op.String())
	}
	v := &BinOp{
		Op: op,
		X:  x,
		Y:  y,
	}
	v.setPos(pos)
	v.setType(t)
	return f.emit(v)
}
func emitCompare(f *Function, op token.Token, x, y Value, pos token.Pos) Value {
	xt := x.Type().Underlying()
	yt := y.Type().Underlying()
	if x == vTrue && op == token.EQL {
		if yt, ok := yt.(*types.Basic); ok && yt.Info()&types.IsBoolean != 0 {
			return y
		}
	}
	if types.Identical(xt, yt) {
	} else if _, ok := xt.(*types.Interface); ok {
		y = emitConv(f, y, x.Type())
	} else if _, ok := yt.(*types.Interface); ok {
		x = emitConv(f, x, y.Type())
	} else if _, ok := x.(*Const); ok {
		x = emitConv(f, x, y.Type())
	} else if _, ok := y.(*Const); ok {
		y = emitConv(f, y, x.Type())
	} else {
	}
	v := &BinOp{
		Op: op,
		X:  x,
		Y:  y,
	}
	v.setPos(pos)
	v.setType(tBool)
	return f.emit(v)
}
func isValuePreserving(ut_src, ut_dst types.Type) bool {
	if structTypesIdentical(ut_dst, ut_src) {
		return true
	}
	switch ut_dst.(type) {
	case *types.Chan:
		_, ok := ut_src.(*types.Chan)
		return ok
	case *types.Pointer:
		_, ok := ut_src.(*types.Pointer)
		return ok
	}
	return false
}