549 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			549 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Go
		
	
	
	
// Copyright 2013 The Go Authors. All rights reserved.
 | 
						||
// Use of this source code is governed by a BSD-style
 | 
						||
// license that can be found in the LICENSE file.
 | 
						||
 | 
						||
package interp
 | 
						||
 | 
						||
// Emulated "reflect" package.
 | 
						||
//
 | 
						||
// We completely replace the built-in "reflect" package.
 | 
						||
// The only thing clients can depend upon are that reflect.Type is an
 | 
						||
// interface and reflect.Value is an (opaque) struct.
 | 
						||
 | 
						||
import (
 | 
						||
	"fmt"
 | 
						||
	"go/token"
 | 
						||
	"reflect"
 | 
						||
	"unsafe"
 | 
						||
 | 
						||
	"llvm.org/llgo/third_party/gotools/go/ssa"
 | 
						||
	"llvm.org/llgo/third_party/gotools/go/types"
 | 
						||
)
 | 
						||
 | 
						||
type opaqueType struct {
 | 
						||
	types.Type
 | 
						||
	name string
 | 
						||
}
 | 
						||
 | 
						||
func (t *opaqueType) String() string { return t.name }
 | 
						||
 | 
						||
// A bogus "reflect" type-checker package.  Shared across interpreters.
 | 
						||
var reflectTypesPackage = types.NewPackage("reflect", "reflect")
 | 
						||
 | 
						||
// rtype is the concrete type the interpreter uses to implement the
 | 
						||
// reflect.Type interface.
 | 
						||
//
 | 
						||
// type rtype <opaque>
 | 
						||
var rtypeType = makeNamedType("rtype", &opaqueType{nil, "rtype"})
 | 
						||
 | 
						||
// error is an (interpreted) named type whose underlying type is string.
 | 
						||
// The interpreter uses it for all implementations of the built-in error
 | 
						||
// interface that it creates.
 | 
						||
// We put it in the "reflect" package for expedience.
 | 
						||
//
 | 
						||
// type error string
 | 
						||
var errorType = makeNamedType("error", &opaqueType{nil, "error"})
 | 
						||
 | 
						||
func makeNamedType(name string, underlying types.Type) *types.Named {
 | 
						||
	obj := types.NewTypeName(token.NoPos, reflectTypesPackage, name, nil)
 | 
						||
	return types.NewNamed(obj, underlying, nil)
 | 
						||
}
 | 
						||
 | 
						||
func makeReflectValue(t types.Type, v value) value {
 | 
						||
	return structure{rtype{t}, v}
 | 
						||
}
 | 
						||
 | 
						||
// Given a reflect.Value, returns its rtype.
 | 
						||
func rV2T(v value) rtype {
 | 
						||
	return v.(structure)[0].(rtype)
 | 
						||
}
 | 
						||
 | 
						||
// Given a reflect.Value, returns the underlying interpreter value.
 | 
						||
func rV2V(v value) value {
 | 
						||
	return v.(structure)[1]
 | 
						||
}
 | 
						||
 | 
						||
// makeReflectType boxes up an rtype in a reflect.Type interface.
 | 
						||
func makeReflectType(rt rtype) value {
 | 
						||
	return iface{rtypeType, rt}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Init(fr *frame, args []value) value {
 | 
						||
	// Signature: func()
 | 
						||
	return nil
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰rtype۰Bits(fr *frame, args []value) value {
 | 
						||
	// Signature: func (t reflect.rtype) int
 | 
						||
	rt := args[0].(rtype).t
 | 
						||
	basic, ok := rt.Underlying().(*types.Basic)
 | 
						||
	if !ok {
 | 
						||
		panic(fmt.Sprintf("reflect.Type.Bits(%T): non-basic type", rt))
 | 
						||
	}
 | 
						||
	return int(fr.i.sizes.Sizeof(basic)) * 8
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰rtype۰Elem(fr *frame, args []value) value {
 | 
						||
	// Signature: func (t reflect.rtype) reflect.Type
 | 
						||
	return makeReflectType(rtype{args[0].(rtype).t.Underlying().(interface {
 | 
						||
		Elem() types.Type
 | 
						||
	}).Elem()})
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰rtype۰Field(fr *frame, args []value) value {
 | 
						||
	// Signature: func (t reflect.rtype, i int) reflect.StructField
 | 
						||
	st := args[0].(rtype).t.Underlying().(*types.Struct)
 | 
						||
	i := args[1].(int)
 | 
						||
	f := st.Field(i)
 | 
						||
	return structure{
 | 
						||
		f.Name(),
 | 
						||
		f.Pkg().Path(),
 | 
						||
		makeReflectType(rtype{f.Type()}),
 | 
						||
		st.Tag(i),
 | 
						||
		0,         // TODO(adonovan): offset
 | 
						||
		[]value{}, // TODO(adonovan): indices
 | 
						||
		f.Anonymous(),
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰rtype۰Kind(fr *frame, args []value) value {
 | 
						||
	// Signature: func (t reflect.rtype) uint
 | 
						||
	return uint(reflectKind(args[0].(rtype).t))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰rtype۰NumField(fr *frame, args []value) value {
 | 
						||
	// Signature: func (t reflect.rtype) int
 | 
						||
	return args[0].(rtype).t.Underlying().(*types.Struct).NumFields()
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰rtype۰NumMethod(fr *frame, args []value) value {
 | 
						||
	// Signature: func (t reflect.rtype) int
 | 
						||
	return fr.i.prog.MethodSets.MethodSet(args[0].(rtype).t).Len()
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰rtype۰NumOut(fr *frame, args []value) value {
 | 
						||
	// Signature: func (t reflect.rtype) int
 | 
						||
	return args[0].(rtype).t.(*types.Signature).Results().Len()
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰rtype۰Out(fr *frame, args []value) value {
 | 
						||
	// Signature: func (t reflect.rtype, i int) int
 | 
						||
	i := args[1].(int)
 | 
						||
	return makeReflectType(rtype{args[0].(rtype).t.(*types.Signature).Results().At(i).Type()})
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰rtype۰Size(fr *frame, args []value) value {
 | 
						||
	// Signature: func (t reflect.rtype) uintptr
 | 
						||
	return uintptr(fr.i.sizes.Sizeof(args[0].(rtype).t))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰rtype۰String(fr *frame, args []value) value {
 | 
						||
	// Signature: func (t reflect.rtype) string
 | 
						||
	return args[0].(rtype).t.String()
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰New(fr *frame, args []value) value {
 | 
						||
	// Signature: func (t reflect.Type) reflect.Value
 | 
						||
	t := args[0].(iface).v.(rtype).t
 | 
						||
	alloc := zero(t)
 | 
						||
	return makeReflectValue(types.NewPointer(t), &alloc)
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰SliceOf(fr *frame, args []value) value {
 | 
						||
	// Signature: func (t reflect.rtype) Type
 | 
						||
	return makeReflectType(rtype{types.NewSlice(args[0].(iface).v.(rtype).t)})
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰TypeOf(fr *frame, args []value) value {
 | 
						||
	// Signature: func (t reflect.rtype) Type
 | 
						||
	return makeReflectType(rtype{args[0].(iface).t})
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰ValueOf(fr *frame, args []value) value {
 | 
						||
	// Signature: func (interface{}) reflect.Value
 | 
						||
	itf := args[0].(iface)
 | 
						||
	return makeReflectValue(itf.t, itf.v)
 | 
						||
}
 | 
						||
 | 
						||
func reflectKind(t types.Type) reflect.Kind {
 | 
						||
	switch t := t.(type) {
 | 
						||
	case *types.Named:
 | 
						||
		return reflectKind(t.Underlying())
 | 
						||
	case *types.Basic:
 | 
						||
		switch t.Kind() {
 | 
						||
		case types.Bool:
 | 
						||
			return reflect.Bool
 | 
						||
		case types.Int:
 | 
						||
			return reflect.Int
 | 
						||
		case types.Int8:
 | 
						||
			return reflect.Int8
 | 
						||
		case types.Int16:
 | 
						||
			return reflect.Int16
 | 
						||
		case types.Int32:
 | 
						||
			return reflect.Int32
 | 
						||
		case types.Int64:
 | 
						||
			return reflect.Int64
 | 
						||
		case types.Uint:
 | 
						||
			return reflect.Uint
 | 
						||
		case types.Uint8:
 | 
						||
			return reflect.Uint8
 | 
						||
		case types.Uint16:
 | 
						||
			return reflect.Uint16
 | 
						||
		case types.Uint32:
 | 
						||
			return reflect.Uint32
 | 
						||
		case types.Uint64:
 | 
						||
			return reflect.Uint64
 | 
						||
		case types.Uintptr:
 | 
						||
			return reflect.Uintptr
 | 
						||
		case types.Float32:
 | 
						||
			return reflect.Float32
 | 
						||
		case types.Float64:
 | 
						||
			return reflect.Float64
 | 
						||
		case types.Complex64:
 | 
						||
			return reflect.Complex64
 | 
						||
		case types.Complex128:
 | 
						||
			return reflect.Complex128
 | 
						||
		case types.String:
 | 
						||
			return reflect.String
 | 
						||
		case types.UnsafePointer:
 | 
						||
			return reflect.UnsafePointer
 | 
						||
		}
 | 
						||
	case *types.Array:
 | 
						||
		return reflect.Array
 | 
						||
	case *types.Chan:
 | 
						||
		return reflect.Chan
 | 
						||
	case *types.Signature:
 | 
						||
		return reflect.Func
 | 
						||
	case *types.Interface:
 | 
						||
		return reflect.Interface
 | 
						||
	case *types.Map:
 | 
						||
		return reflect.Map
 | 
						||
	case *types.Pointer:
 | 
						||
		return reflect.Ptr
 | 
						||
	case *types.Slice:
 | 
						||
		return reflect.Slice
 | 
						||
	case *types.Struct:
 | 
						||
		return reflect.Struct
 | 
						||
	}
 | 
						||
	panic(fmt.Sprint("unexpected type: ", t))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰Kind(fr *frame, args []value) value {
 | 
						||
	// Signature: func (reflect.Value) uint
 | 
						||
	return uint(reflectKind(rV2T(args[0]).t))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰String(fr *frame, args []value) value {
 | 
						||
	// Signature: func (reflect.Value) string
 | 
						||
	return toString(rV2V(args[0]))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰Type(fr *frame, args []value) value {
 | 
						||
	// Signature: func (reflect.Value) reflect.Type
 | 
						||
	return makeReflectType(rV2T(args[0]))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰Uint(fr *frame, args []value) value {
 | 
						||
	// Signature: func (reflect.Value) uint64
 | 
						||
	switch v := rV2V(args[0]).(type) {
 | 
						||
	case uint:
 | 
						||
		return uint64(v)
 | 
						||
	case uint8:
 | 
						||
		return uint64(v)
 | 
						||
	case uint16:
 | 
						||
		return uint64(v)
 | 
						||
	case uint32:
 | 
						||
		return uint64(v)
 | 
						||
	case uint64:
 | 
						||
		return uint64(v)
 | 
						||
	case uintptr:
 | 
						||
		return uint64(v)
 | 
						||
	}
 | 
						||
	panic("reflect.Value.Uint")
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰Len(fr *frame, args []value) value {
 | 
						||
	// Signature: func (reflect.Value) int
 | 
						||
	switch v := rV2V(args[0]).(type) {
 | 
						||
	case string:
 | 
						||
		return len(v)
 | 
						||
	case array:
 | 
						||
		return len(v)
 | 
						||
	case chan value:
 | 
						||
		return cap(v)
 | 
						||
	case []value:
 | 
						||
		return len(v)
 | 
						||
	case *hashmap:
 | 
						||
		return v.len()
 | 
						||
	case map[value]value:
 | 
						||
		return len(v)
 | 
						||
	default:
 | 
						||
		panic(fmt.Sprintf("reflect.(Value).Len(%v)", v))
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰MapIndex(fr *frame, args []value) value {
 | 
						||
	// Signature: func (reflect.Value) Value
 | 
						||
	tValue := rV2T(args[0]).t.Underlying().(*types.Map).Key()
 | 
						||
	k := rV2V(args[1])
 | 
						||
	switch m := rV2V(args[0]).(type) {
 | 
						||
	case map[value]value:
 | 
						||
		if v, ok := m[k]; ok {
 | 
						||
			return makeReflectValue(tValue, v)
 | 
						||
		}
 | 
						||
 | 
						||
	case *hashmap:
 | 
						||
		if v := m.lookup(k.(hashable)); v != nil {
 | 
						||
			return makeReflectValue(tValue, v)
 | 
						||
		}
 | 
						||
 | 
						||
	default:
 | 
						||
		panic(fmt.Sprintf("(reflect.Value).MapIndex(%T, %T)", m, k))
 | 
						||
	}
 | 
						||
	return makeReflectValue(nil, nil)
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰MapKeys(fr *frame, args []value) value {
 | 
						||
	// Signature: func (reflect.Value) []Value
 | 
						||
	var keys []value
 | 
						||
	tKey := rV2T(args[0]).t.Underlying().(*types.Map).Key()
 | 
						||
	switch v := rV2V(args[0]).(type) {
 | 
						||
	case map[value]value:
 | 
						||
		for k := range v {
 | 
						||
			keys = append(keys, makeReflectValue(tKey, k))
 | 
						||
		}
 | 
						||
 | 
						||
	case *hashmap:
 | 
						||
		for _, e := range v.table {
 | 
						||
			for ; e != nil; e = e.next {
 | 
						||
				keys = append(keys, makeReflectValue(tKey, e.key))
 | 
						||
			}
 | 
						||
		}
 | 
						||
 | 
						||
	default:
 | 
						||
		panic(fmt.Sprintf("(reflect.Value).MapKeys(%T)", v))
 | 
						||
	}
 | 
						||
	return keys
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰NumField(fr *frame, args []value) value {
 | 
						||
	// Signature: func (reflect.Value) int
 | 
						||
	return len(rV2V(args[0]).(structure))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰NumMethod(fr *frame, args []value) value {
 | 
						||
	// Signature: func (reflect.Value) int
 | 
						||
	return fr.i.prog.MethodSets.MethodSet(rV2T(args[0]).t).Len()
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰Pointer(fr *frame, args []value) value {
 | 
						||
	// Signature: func (v reflect.Value) uintptr
 | 
						||
	switch v := rV2V(args[0]).(type) {
 | 
						||
	case *value:
 | 
						||
		return uintptr(unsafe.Pointer(v))
 | 
						||
	case chan value:
 | 
						||
		return reflect.ValueOf(v).Pointer()
 | 
						||
	case []value:
 | 
						||
		return reflect.ValueOf(v).Pointer()
 | 
						||
	case *hashmap:
 | 
						||
		return reflect.ValueOf(v.table).Pointer()
 | 
						||
	case map[value]value:
 | 
						||
		return reflect.ValueOf(v).Pointer()
 | 
						||
	case *ssa.Function:
 | 
						||
		return uintptr(unsafe.Pointer(v))
 | 
						||
	case *closure:
 | 
						||
		return uintptr(unsafe.Pointer(v))
 | 
						||
	default:
 | 
						||
		panic(fmt.Sprintf("reflect.(Value).Pointer(%T)", v))
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰Index(fr *frame, args []value) value {
 | 
						||
	// Signature: func (v reflect.Value, i int) Value
 | 
						||
	i := args[1].(int)
 | 
						||
	t := rV2T(args[0]).t.Underlying()
 | 
						||
	switch v := rV2V(args[0]).(type) {
 | 
						||
	case array:
 | 
						||
		return makeReflectValue(t.(*types.Array).Elem(), v[i])
 | 
						||
	case []value:
 | 
						||
		return makeReflectValue(t.(*types.Slice).Elem(), v[i])
 | 
						||
	default:
 | 
						||
		panic(fmt.Sprintf("reflect.(Value).Index(%T)", v))
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰Bool(fr *frame, args []value) value {
 | 
						||
	// Signature: func (reflect.Value) bool
 | 
						||
	return rV2V(args[0]).(bool)
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰CanAddr(fr *frame, args []value) value {
 | 
						||
	// Signature: func (v reflect.Value) bool
 | 
						||
	// Always false for our representation.
 | 
						||
	return false
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰CanInterface(fr *frame, args []value) value {
 | 
						||
	// Signature: func (v reflect.Value) bool
 | 
						||
	// Always true for our representation.
 | 
						||
	return true
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰Elem(fr *frame, args []value) value {
 | 
						||
	// Signature: func (v reflect.Value) reflect.Value
 | 
						||
	switch x := rV2V(args[0]).(type) {
 | 
						||
	case iface:
 | 
						||
		return makeReflectValue(x.t, x.v)
 | 
						||
	case *value:
 | 
						||
		return makeReflectValue(rV2T(args[0]).t.Underlying().(*types.Pointer).Elem(), *x)
 | 
						||
	default:
 | 
						||
		panic(fmt.Sprintf("reflect.(Value).Elem(%T)", x))
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰Field(fr *frame, args []value) value {
 | 
						||
	// Signature: func (v reflect.Value, i int) reflect.Value
 | 
						||
	v := args[0]
 | 
						||
	i := args[1].(int)
 | 
						||
	return makeReflectValue(rV2T(v).t.Underlying().(*types.Struct).Field(i).Type(), rV2V(v).(structure)[i])
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰Float(fr *frame, args []value) value {
 | 
						||
	// Signature: func (reflect.Value) float64
 | 
						||
	switch v := rV2V(args[0]).(type) {
 | 
						||
	case float32:
 | 
						||
		return float64(v)
 | 
						||
	case float64:
 | 
						||
		return float64(v)
 | 
						||
	}
 | 
						||
	panic("reflect.Value.Float")
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰Interface(fr *frame, args []value) value {
 | 
						||
	// Signature: func (v reflect.Value) interface{}
 | 
						||
	return ext۰reflect۰valueInterface(fr, args)
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰Int(fr *frame, args []value) value {
 | 
						||
	// Signature: func (reflect.Value) int64
 | 
						||
	switch x := rV2V(args[0]).(type) {
 | 
						||
	case int:
 | 
						||
		return int64(x)
 | 
						||
	case int8:
 | 
						||
		return int64(x)
 | 
						||
	case int16:
 | 
						||
		return int64(x)
 | 
						||
	case int32:
 | 
						||
		return int64(x)
 | 
						||
	case int64:
 | 
						||
		return x
 | 
						||
	default:
 | 
						||
		panic(fmt.Sprintf("reflect.(Value).Int(%T)", x))
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰IsNil(fr *frame, args []value) value {
 | 
						||
	// Signature: func (reflect.Value) bool
 | 
						||
	switch x := rV2V(args[0]).(type) {
 | 
						||
	case *value:
 | 
						||
		return x == nil
 | 
						||
	case chan value:
 | 
						||
		return x == nil
 | 
						||
	case map[value]value:
 | 
						||
		return x == nil
 | 
						||
	case *hashmap:
 | 
						||
		return x == nil
 | 
						||
	case iface:
 | 
						||
		return x.t == nil
 | 
						||
	case []value:
 | 
						||
		return x == nil
 | 
						||
	case *ssa.Function:
 | 
						||
		return x == nil
 | 
						||
	case *ssa.Builtin:
 | 
						||
		return x == nil
 | 
						||
	case *closure:
 | 
						||
		return x == nil
 | 
						||
	default:
 | 
						||
		panic(fmt.Sprintf("reflect.(Value).IsNil(%T)", x))
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰IsValid(fr *frame, args []value) value {
 | 
						||
	// Signature: func (reflect.Value) bool
 | 
						||
	return rV2V(args[0]) != nil
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰Value۰Set(fr *frame, args []value) value {
 | 
						||
	// TODO(adonovan): implement.
 | 
						||
	return nil
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰valueInterface(fr *frame, args []value) value {
 | 
						||
	// Signature: func (v reflect.Value, safe bool) interface{}
 | 
						||
	v := args[0].(structure)
 | 
						||
	return iface{rV2T(v).t, rV2V(v)}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰reflect۰error۰Error(fr *frame, args []value) value {
 | 
						||
	return args[0]
 | 
						||
}
 | 
						||
 | 
						||
// newMethod creates a new method of the specified name, package and receiver type.
 | 
						||
func newMethod(pkg *ssa.Package, recvType types.Type, name string) *ssa.Function {
 | 
						||
	// TODO(adonovan): fix: hack: currently the only part of Signature
 | 
						||
	// that is needed is the "pointerness" of Recv.Type, and for
 | 
						||
	// now, we'll set it to always be false since we're only
 | 
						||
	// concerned with rtype.  Encapsulate this better.
 | 
						||
	sig := types.NewSignature(nil, types.NewVar(token.NoPos, nil, "recv", recvType), nil, nil, false)
 | 
						||
	fn := pkg.Prog.NewFunction(name, sig, "fake reflect method")
 | 
						||
	fn.Pkg = pkg
 | 
						||
	return fn
 | 
						||
}
 | 
						||
 | 
						||
func initReflect(i *interpreter) {
 | 
						||
	i.reflectPackage = &ssa.Package{
 | 
						||
		Prog:    i.prog,
 | 
						||
		Object:  reflectTypesPackage,
 | 
						||
		Members: make(map[string]ssa.Member),
 | 
						||
	}
 | 
						||
 | 
						||
	// Clobber the type-checker's notion of reflect.Value's
 | 
						||
	// underlying type so that it more closely matches the fake one
 | 
						||
	// (at least in the number of fields---we lie about the type of
 | 
						||
	// the rtype field).
 | 
						||
	//
 | 
						||
	// We must ensure that calls to (ssa.Value).Type() return the
 | 
						||
	// fake type so that correct "shape" is used when allocating
 | 
						||
	// variables, making zero values, loading, and storing.
 | 
						||
	//
 | 
						||
	// TODO(adonovan): obviously this is a hack.  We need a cleaner
 | 
						||
	// way to fake the reflect package (almost---DeepEqual is fine).
 | 
						||
	// One approach would be not to even load its source code, but
 | 
						||
	// provide fake source files.  This would guarantee that no bad
 | 
						||
	// information leaks into other packages.
 | 
						||
	if r := i.prog.ImportedPackage("reflect"); r != nil {
 | 
						||
		rV := r.Object.Scope().Lookup("Value").Type().(*types.Named)
 | 
						||
		tEface := types.NewInterface(nil, nil).Complete()
 | 
						||
		rV.SetUnderlying(types.NewStruct([]*types.Var{
 | 
						||
			types.NewField(token.NoPos, r.Object, "t", tEface, false), // a lie
 | 
						||
			types.NewField(token.NoPos, r.Object, "v", tEface, false),
 | 
						||
		}, nil))
 | 
						||
	}
 | 
						||
 | 
						||
	i.rtypeMethods = methodSet{
 | 
						||
		"Bits":      newMethod(i.reflectPackage, rtypeType, "Bits"),
 | 
						||
		"Elem":      newMethod(i.reflectPackage, rtypeType, "Elem"),
 | 
						||
		"Field":     newMethod(i.reflectPackage, rtypeType, "Field"),
 | 
						||
		"Kind":      newMethod(i.reflectPackage, rtypeType, "Kind"),
 | 
						||
		"NumField":  newMethod(i.reflectPackage, rtypeType, "NumField"),
 | 
						||
		"NumMethod": newMethod(i.reflectPackage, rtypeType, "NumMethod"),
 | 
						||
		"NumOut":    newMethod(i.reflectPackage, rtypeType, "NumOut"),
 | 
						||
		"Out":       newMethod(i.reflectPackage, rtypeType, "Out"),
 | 
						||
		"Size":      newMethod(i.reflectPackage, rtypeType, "Size"),
 | 
						||
		"String":    newMethod(i.reflectPackage, rtypeType, "String"),
 | 
						||
	}
 | 
						||
	i.errorMethods = methodSet{
 | 
						||
		"Error": newMethod(i.reflectPackage, errorType, "Error"),
 | 
						||
	}
 | 
						||
}
 |