github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/tools/go/ssa/interp/external14.go (about)

     1  // Copyright 2013 The Go Authors.  All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // +build !go1.5
     6  
     7  package interp
     8  
     9  // Emulated functions that we cannot interpret because they are
    10  // external or because they use "unsafe" or "reflect" operations.
    11  
    12  import (
    13  	"math"
    14  	"os"
    15  	"runtime"
    16  	"strings"
    17  	"syscall"
    18  	"time"
    19  	"unsafe"
    20  
    21  	"golang.org/x/tools/go/ssa"
    22  	"golang.org/x/tools/go/types"
    23  )
    24  
    25  type externalFn func(fr *frame, args []value) value
    26  
    27  // TODO(adonovan): fix: reflect.Value abstracts an lvalue or an
    28  // rvalue; Set() causes mutations that can be observed via aliases.
    29  // We have not captured that correctly here.
    30  
    31  // Key strings are from Function.String().
    32  var externals map[string]externalFn
    33  
    34  func init() {
    35  	// That little dot ۰ is an Arabic zero numeral (U+06F0), categories [Nd].
    36  	externals = map[string]externalFn{
    37  		"(*sync.Pool).Get":                 ext۰sync۰Pool۰Get,
    38  		"(*sync.Pool).Put":                 ext۰sync۰Pool۰Put,
    39  		"(reflect.Value).Bool":             ext۰reflect۰Value۰Bool,
    40  		"(reflect.Value).CanAddr":          ext۰reflect۰Value۰CanAddr,
    41  		"(reflect.Value).CanInterface":     ext۰reflect۰Value۰CanInterface,
    42  		"(reflect.Value).Elem":             ext۰reflect۰Value۰Elem,
    43  		"(reflect.Value).Field":            ext۰reflect۰Value۰Field,
    44  		"(reflect.Value).Float":            ext۰reflect۰Value۰Float,
    45  		"(reflect.Value).Index":            ext۰reflect۰Value۰Index,
    46  		"(reflect.Value).Int":              ext۰reflect۰Value۰Int,
    47  		"(reflect.Value).Interface":        ext۰reflect۰Value۰Interface,
    48  		"(reflect.Value).IsNil":            ext۰reflect۰Value۰IsNil,
    49  		"(reflect.Value).IsValid":          ext۰reflect۰Value۰IsValid,
    50  		"(reflect.Value).Kind":             ext۰reflect۰Value۰Kind,
    51  		"(reflect.Value).Len":              ext۰reflect۰Value۰Len,
    52  		"(reflect.Value).MapIndex":         ext۰reflect۰Value۰MapIndex,
    53  		"(reflect.Value).MapKeys":          ext۰reflect۰Value۰MapKeys,
    54  		"(reflect.Value).NumField":         ext۰reflect۰Value۰NumField,
    55  		"(reflect.Value).NumMethod":        ext۰reflect۰Value۰NumMethod,
    56  		"(reflect.Value).Pointer":          ext۰reflect۰Value۰Pointer,
    57  		"(reflect.Value).Set":              ext۰reflect۰Value۰Set,
    58  		"(reflect.Value).String":           ext۰reflect۰Value۰String,
    59  		"(reflect.Value).Type":             ext۰reflect۰Value۰Type,
    60  		"(reflect.Value).Uint":             ext۰reflect۰Value۰Uint,
    61  		"(reflect.error).Error":            ext۰reflect۰error۰Error,
    62  		"(reflect.rtype).Bits":             ext۰reflect۰rtype۰Bits,
    63  		"(reflect.rtype).Elem":             ext۰reflect۰rtype۰Elem,
    64  		"(reflect.rtype).Field":            ext۰reflect۰rtype۰Field,
    65  		"(reflect.rtype).In":               ext۰reflect۰rtype۰In,
    66  		"(reflect.rtype).Kind":             ext۰reflect۰rtype۰Kind,
    67  		"(reflect.rtype).NumField":         ext۰reflect۰rtype۰NumField,
    68  		"(reflect.rtype).NumIn":            ext۰reflect۰rtype۰NumIn,
    69  		"(reflect.rtype).NumMethod":        ext۰reflect۰rtype۰NumMethod,
    70  		"(reflect.rtype).NumOut":           ext۰reflect۰rtype۰NumOut,
    71  		"(reflect.rtype).Out":              ext۰reflect۰rtype۰Out,
    72  		"(reflect.rtype).Size":             ext۰reflect۰rtype۰Size,
    73  		"(reflect.rtype).String":           ext۰reflect۰rtype۰String,
    74  		"bytes.Equal":                      ext۰bytes۰Equal,
    75  		"bytes.IndexByte":                  ext۰bytes۰IndexByte,
    76  		"hash/crc32.haveSSE42":             ext۰crc32۰haveSSE42,
    77  		"math.Abs":                         ext۰math۰Abs,
    78  		"math.Exp":                         ext۰math۰Exp,
    79  		"math.Float32bits":                 ext۰math۰Float32bits,
    80  		"math.Float32frombits":             ext۰math۰Float32frombits,
    81  		"math.Float64bits":                 ext۰math۰Float64bits,
    82  		"math.Float64frombits":             ext۰math۰Float64frombits,
    83  		"math.Ldexp":                       ext۰math۰Ldexp,
    84  		"math.Log":                         ext۰math۰Log,
    85  		"math.Min":                         ext۰math۰Min,
    86  		"math.hasSSE4":                     ext۰math۰hasSSE4,
    87  		"os.Pipe":                          ext۰os۰Pipe,
    88  		"os.runtime_args":                  ext۰os۰runtime_args,
    89  		"os.runtime_beforeExit":            ext۰os۰runtime_beforeExit,
    90  		"reflect.New":                      ext۰reflect۰New,
    91  		"reflect.SliceOf":                  ext۰reflect۰SliceOf,
    92  		"reflect.TypeOf":                   ext۰reflect۰TypeOf,
    93  		"reflect.ValueOf":                  ext۰reflect۰ValueOf,
    94  		"reflect.Zero":                     ext۰reflect۰Zero,
    95  		"reflect.init":                     ext۰reflect۰Init,
    96  		"reflect.valueInterface":           ext۰reflect۰valueInterface,
    97  		"runtime.Breakpoint":               ext۰runtime۰Breakpoint,
    98  		"runtime.Caller":                   ext۰runtime۰Caller,
    99  		"runtime.Callers":                  ext۰runtime۰Callers,
   100  		"runtime.FuncForPC":                ext۰runtime۰FuncForPC,
   101  		"runtime.GC":                       ext۰runtime۰GC,
   102  		"runtime.GOMAXPROCS":               ext۰runtime۰GOMAXPROCS,
   103  		"runtime.Goexit":                   ext۰runtime۰Goexit,
   104  		"runtime.Gosched":                  ext۰runtime۰Gosched,
   105  		"runtime.init":                     ext۰runtime۰init,
   106  		"runtime.NumCPU":                   ext۰runtime۰NumCPU,
   107  		"runtime.ReadMemStats":             ext۰runtime۰ReadMemStats,
   108  		"runtime.SetFinalizer":             ext۰runtime۰SetFinalizer,
   109  		"(*runtime.Func).Entry":            ext۰runtime۰Func۰Entry,
   110  		"(*runtime.Func).FileLine":         ext۰runtime۰Func۰FileLine,
   111  		"(*runtime.Func).Name":             ext۰runtime۰Func۰Name,
   112  		"runtime.environ":                  ext۰runtime۰environ,
   113  		"runtime.getgoroot":                ext۰runtime۰getgoroot,
   114  		"strings.Index":                    ext۰strings۰Index,
   115  		"strings.IndexByte":                ext۰strings۰IndexByte,
   116  		"sync.runtime_Semacquire":          ext۰sync۰runtime_Semacquire,
   117  		"sync.runtime_Semrelease":          ext۰sync۰runtime_Semrelease,
   118  		"sync.runtime_Syncsemcheck":        ext۰sync۰runtime_Syncsemcheck,
   119  		"sync.runtime_registerPoolCleanup": ext۰sync۰runtime_registerPoolCleanup,
   120  		"sync/atomic.AddInt32":             ext۰atomic۰AddInt32,
   121  		"sync/atomic.AddUint32":            ext۰atomic۰AddUint32,
   122  		"sync/atomic.AddUint64":            ext۰atomic۰AddUint64,
   123  		"sync/atomic.CompareAndSwapInt32":  ext۰atomic۰CompareAndSwapInt32,
   124  		"sync/atomic.LoadInt32":            ext۰atomic۰LoadInt32,
   125  		"sync/atomic.LoadUint32":           ext۰atomic۰LoadUint32,
   126  		"sync/atomic.StoreInt32":           ext۰atomic۰StoreInt32,
   127  		"sync/atomic.StoreUint32":          ext۰atomic۰StoreUint32,
   128  		"syscall.Close":                    ext۰syscall۰Close,
   129  		"syscall.Exit":                     ext۰syscall۰Exit,
   130  		"syscall.Fstat":                    ext۰syscall۰Fstat,
   131  		"syscall.Getpid":                   ext۰syscall۰Getpid,
   132  		"syscall.Getwd":                    ext۰syscall۰Getwd,
   133  		"syscall.Kill":                     ext۰syscall۰Kill,
   134  		"syscall.Lstat":                    ext۰syscall۰Lstat,
   135  		"syscall.Open":                     ext۰syscall۰Open,
   136  		"syscall.ParseDirent":              ext۰syscall۰ParseDirent,
   137  		"syscall.RawSyscall":               ext۰syscall۰RawSyscall,
   138  		"syscall.Read":                     ext۰syscall۰Read,
   139  		"syscall.ReadDirent":               ext۰syscall۰ReadDirent,
   140  		"syscall.Stat":                     ext۰syscall۰Stat,
   141  		"syscall.Write":                    ext۰syscall۰Write,
   142  		"syscall.runtime_envs":             ext۰runtime۰environ,
   143  		"testing.runExample":               ext۰testing۰runExample,
   144  		"time.Sleep":                       ext۰time۰Sleep,
   145  		"time.now":                         ext۰time۰now,
   146  	}
   147  }
   148  
   149  // wrapError returns an interpreted 'error' interface value for err.
   150  func wrapError(err error) value {
   151  	if err == nil {
   152  		return iface{}
   153  	}
   154  	return iface{t: errorType, v: err.Error()}
   155  }
   156  
   157  func ext۰sync۰Pool۰Get(fr *frame, args []value) value {
   158  	Pool := fr.i.prog.ImportedPackage("sync").Type("Pool").Object()
   159  	_, newIndex, _ := types.LookupFieldOrMethod(Pool.Type(), false, Pool.Pkg(), "New")
   160  
   161  	if New := (*args[0].(*value)).(structure)[newIndex[0]]; New != nil {
   162  		return call(fr.i, fr, 0, New, nil)
   163  	}
   164  	return nil
   165  }
   166  
   167  func ext۰sync۰Pool۰Put(fr *frame, args []value) value {
   168  	return nil
   169  }
   170  
   171  func ext۰bytes۰Equal(fr *frame, args []value) value {
   172  	// func Equal(a, b []byte) bool
   173  	a := args[0].([]value)
   174  	b := args[1].([]value)
   175  	if len(a) != len(b) {
   176  		return false
   177  	}
   178  	for i := range a {
   179  		if a[i] != b[i] {
   180  			return false
   181  		}
   182  	}
   183  	return true
   184  }
   185  
   186  func ext۰bytes۰IndexByte(fr *frame, args []value) value {
   187  	// func IndexByte(s []byte, c byte) int
   188  	s := args[0].([]value)
   189  	c := args[1].(byte)
   190  	for i, b := range s {
   191  		if b.(byte) == c {
   192  			return i
   193  		}
   194  	}
   195  	return -1
   196  }
   197  
   198  func ext۰crc32۰haveSSE42(fr *frame, args []value) value {
   199  	return false
   200  }
   201  
   202  func ext۰math۰Float64frombits(fr *frame, args []value) value {
   203  	return math.Float64frombits(args[0].(uint64))
   204  }
   205  
   206  func ext۰math۰Float64bits(fr *frame, args []value) value {
   207  	return math.Float64bits(args[0].(float64))
   208  }
   209  
   210  func ext۰math۰Float32frombits(fr *frame, args []value) value {
   211  	return math.Float32frombits(args[0].(uint32))
   212  }
   213  
   214  func ext۰math۰Abs(fr *frame, args []value) value {
   215  	return math.Abs(args[0].(float64))
   216  }
   217  
   218  func ext۰math۰Exp(fr *frame, args []value) value {
   219  	return math.Exp(args[0].(float64))
   220  }
   221  
   222  func ext۰math۰Float32bits(fr *frame, args []value) value {
   223  	return math.Float32bits(args[0].(float32))
   224  }
   225  
   226  func ext۰math۰Min(fr *frame, args []value) value {
   227  	return math.Min(args[0].(float64), args[1].(float64))
   228  }
   229  
   230  func ext۰math۰hasSSE4(fr *frame, args []value) value {
   231  	return false
   232  }
   233  
   234  func ext۰math۰Ldexp(fr *frame, args []value) value {
   235  	return math.Ldexp(args[0].(float64), args[1].(int))
   236  }
   237  
   238  func ext۰math۰Log(fr *frame, args []value) value {
   239  	return math.Log(args[0].(float64))
   240  }
   241  
   242  func ext۰os۰runtime_args(fr *frame, args []value) value {
   243  	return fr.i.osArgs
   244  }
   245  
   246  func ext۰os۰runtime_beforeExit(fr *frame, args []value) value {
   247  	return nil
   248  }
   249  
   250  func ext۰runtime۰Breakpoint(fr *frame, args []value) value {
   251  	runtime.Breakpoint()
   252  	return nil
   253  }
   254  
   255  func ext۰runtime۰Caller(fr *frame, args []value) value {
   256  	// func Caller(skip int) (pc uintptr, file string, line int, ok bool)
   257  	skip := 1 + args[0].(int)
   258  	for i := 0; i < skip; i++ {
   259  		if fr != nil {
   260  			fr = fr.caller
   261  		}
   262  	}
   263  	var pc uintptr
   264  	var file string
   265  	var line int
   266  	var ok bool
   267  	if fr != nil {
   268  		fn := fr.fn
   269  		// TODO(adonovan): use pc/posn of current instruction, not start of fn.
   270  		// (Required to interpret the log package's tests.)
   271  		pc = uintptr(unsafe.Pointer(fn))
   272  		posn := fn.Prog.Fset.Position(fn.Pos())
   273  		file = posn.Filename
   274  		line = posn.Line
   275  		ok = true
   276  	}
   277  	return tuple{pc, file, line, ok}
   278  }
   279  
   280  func ext۰runtime۰Callers(fr *frame, args []value) value {
   281  	// Callers(skip int, pc []uintptr) int
   282  	skip := args[0].(int)
   283  	pc := args[1].([]value)
   284  	for i := 0; i < skip; i++ {
   285  		if fr != nil {
   286  			fr = fr.caller
   287  		}
   288  	}
   289  	i := 0
   290  	for fr != nil {
   291  		pc[i] = uintptr(unsafe.Pointer(fr.fn))
   292  		i++
   293  		fr = fr.caller
   294  	}
   295  	return i
   296  }
   297  
   298  func ext۰runtime۰FuncForPC(fr *frame, args []value) value {
   299  	// FuncForPC(pc uintptr) *Func
   300  	pc := args[0].(uintptr)
   301  	var fn *ssa.Function
   302  	if pc != 0 {
   303  		fn = (*ssa.Function)(unsafe.Pointer(pc)) // indeed unsafe!
   304  	}
   305  	var Func value
   306  	Func = structure{fn} // a runtime.Func
   307  	return &Func
   308  }
   309  
   310  func ext۰runtime۰environ(fr *frame, args []value) value {
   311  	// This function also implements syscall.runtime_envs.
   312  	return environ
   313  }
   314  
   315  func ext۰runtime۰getgoroot(fr *frame, args []value) value {
   316  	return os.Getenv("GOROOT")
   317  }
   318  
   319  func ext۰strings۰IndexByte(fr *frame, args []value) value {
   320  	// func IndexByte(s string, c byte) int
   321  	s := args[0].(string)
   322  	c := args[1].(byte)
   323  	for i := 0; i < len(s); i++ {
   324  		if s[i] == c {
   325  			return i
   326  		}
   327  	}
   328  	return -1
   329  }
   330  
   331  func ext۰strings۰Index(fr *frame, args []value) value {
   332  	// Call compiled version to avoid tricky asm dependency.
   333  	return strings.Index(args[0].(string), args[1].(string))
   334  }
   335  
   336  func ext۰sync۰runtime_Syncsemcheck(fr *frame, args []value) value {
   337  	// TODO(adonovan): fix: implement.
   338  	return nil
   339  }
   340  
   341  func ext۰sync۰runtime_registerPoolCleanup(fr *frame, args []value) value {
   342  	return nil
   343  }
   344  
   345  func ext۰sync۰runtime_Semacquire(fr *frame, args []value) value {
   346  	// TODO(adonovan): fix: implement.
   347  	return nil
   348  }
   349  
   350  func ext۰sync۰runtime_Semrelease(fr *frame, args []value) value {
   351  	// TODO(adonovan): fix: implement.
   352  	return nil
   353  }
   354  
   355  func ext۰runtime۰GOMAXPROCS(fr *frame, args []value) value {
   356  	// Ignore args[0]; don't let the interpreted program
   357  	// set the interpreter's GOMAXPROCS!
   358  	return runtime.GOMAXPROCS(0)
   359  }
   360  
   361  func ext۰runtime۰Goexit(fr *frame, args []value) value {
   362  	// TODO(adonovan): don't kill the interpreter's main goroutine.
   363  	runtime.Goexit()
   364  	return nil
   365  }
   366  
   367  func ext۰runtime۰GC(fr *frame, args []value) value {
   368  	runtime.GC()
   369  	return nil
   370  }
   371  
   372  func ext۰runtime۰Gosched(fr *frame, args []value) value {
   373  	runtime.Gosched()
   374  	return nil
   375  }
   376  
   377  func ext۰runtime۰init(fr *frame, args []value) value {
   378  	return nil
   379  }
   380  
   381  func ext۰runtime۰NumCPU(fr *frame, args []value) value {
   382  	return runtime.NumCPU()
   383  }
   384  
   385  func ext۰runtime۰ReadMemStats(fr *frame, args []value) value {
   386  	// TODO(adonovan): populate args[0].(Struct)
   387  	return nil
   388  }
   389  
   390  func ext۰atomic۰LoadUint32(fr *frame, args []value) value {
   391  	// TODO(adonovan): fix: not atomic!
   392  	return (*args[0].(*value)).(uint32)
   393  }
   394  
   395  func ext۰atomic۰StoreUint32(fr *frame, args []value) value {
   396  	// TODO(adonovan): fix: not atomic!
   397  	*args[0].(*value) = args[1].(uint32)
   398  	return nil
   399  }
   400  
   401  func ext۰atomic۰LoadInt32(fr *frame, args []value) value {
   402  	// TODO(adonovan): fix: not atomic!
   403  	return (*args[0].(*value)).(int32)
   404  }
   405  
   406  func ext۰atomic۰StoreInt32(fr *frame, args []value) value {
   407  	// TODO(adonovan): fix: not atomic!
   408  	*args[0].(*value) = args[1].(int32)
   409  	return nil
   410  }
   411  
   412  func ext۰atomic۰CompareAndSwapInt32(fr *frame, args []value) value {
   413  	// TODO(adonovan): fix: not atomic!
   414  	p := args[0].(*value)
   415  	if (*p).(int32) == args[1].(int32) {
   416  		*p = args[2].(int32)
   417  		return true
   418  	}
   419  	return false
   420  }
   421  
   422  func ext۰atomic۰AddInt32(fr *frame, args []value) value {
   423  	// TODO(adonovan): fix: not atomic!
   424  	p := args[0].(*value)
   425  	newv := (*p).(int32) + args[1].(int32)
   426  	*p = newv
   427  	return newv
   428  }
   429  
   430  func ext۰atomic۰AddUint32(fr *frame, args []value) value {
   431  	// TODO(adonovan): fix: not atomic!
   432  	p := args[0].(*value)
   433  	newv := (*p).(uint32) + args[1].(uint32)
   434  	*p = newv
   435  	return newv
   436  }
   437  
   438  func ext۰atomic۰AddUint64(fr *frame, args []value) value {
   439  	// TODO(adonovan): fix: not atomic!
   440  	p := args[0].(*value)
   441  	newv := (*p).(uint64) + args[1].(uint64)
   442  	*p = newv
   443  	return newv
   444  }
   445  
   446  func ext۰runtime۰SetFinalizer(fr *frame, args []value) value {
   447  	return nil // ignore
   448  }
   449  
   450  // Pretend: type runtime.Func struct { entry *ssa.Function }
   451  
   452  func ext۰runtime۰Func۰FileLine(fr *frame, args []value) value {
   453  	// func (*runtime.Func) FileLine(uintptr) (string, int)
   454  	f, _ := (*args[0].(*value)).(structure)[0].(*ssa.Function)
   455  	pc := args[1].(uintptr)
   456  	_ = pc
   457  	if f != nil {
   458  		// TODO(adonovan): use position of current instruction, not fn.
   459  		posn := f.Prog.Fset.Position(f.Pos())
   460  		return tuple{posn.Filename, posn.Line}
   461  	}
   462  	return tuple{"", 0}
   463  }
   464  
   465  func ext۰runtime۰Func۰Name(fr *frame, args []value) value {
   466  	// func (*runtime.Func) Name() string
   467  	f, _ := (*args[0].(*value)).(structure)[0].(*ssa.Function)
   468  	if f != nil {
   469  		return f.String()
   470  	}
   471  	return ""
   472  }
   473  
   474  func ext۰runtime۰Func۰Entry(fr *frame, args []value) value {
   475  	// func (*runtime.Func) Entry() uintptr
   476  	f, _ := (*args[0].(*value)).(structure)[0].(*ssa.Function)
   477  	return uintptr(unsafe.Pointer(f))
   478  }
   479  
   480  // This is a workaround for a bug in go/ssa/testmain.go: it creates
   481  // InternalExamples even for Example functions with no Output comment.
   482  // TODO(adonovan): fix (and redesign) testmain.go after Go 1.6.
   483  func ext۰testing۰runExample(fr *frame, args []value) value {
   484  	// This is a stripped down runExample that simply calls the function.
   485  	// It does not capture and compare output nor recover from panic.
   486  	//
   487  	// func runExample(eg testing.InternalExample) bool {
   488  	//     eg.F()
   489  	//     return true
   490  	// }
   491  	F := args[0].(structure)[1]
   492  	call(fr.i, fr, 0, F, nil)
   493  	return true
   494  }
   495  
   496  func ext۰time۰now(fr *frame, args []value) value {
   497  	nano := time.Now().UnixNano()
   498  	return tuple{int64(nano / 1e9), int32(nano % 1e9)}
   499  }
   500  
   501  func ext۰time۰Sleep(fr *frame, args []value) value {
   502  	time.Sleep(time.Duration(args[0].(int64)))
   503  	return nil
   504  }
   505  
   506  func ext۰syscall۰Exit(fr *frame, args []value) value {
   507  	panic(exitPanic(args[0].(int)))
   508  }
   509  
   510  func ext۰syscall۰Getwd(fr *frame, args []value) value {
   511  	s, err := syscall.Getwd()
   512  	return tuple{s, wrapError(err)}
   513  }
   514  
   515  func ext۰syscall۰Getpid(fr *frame, args []value) value {
   516  	return syscall.Getpid()
   517  }
   518  
   519  func valueToBytes(v value) []byte {
   520  	in := v.([]value)
   521  	b := make([]byte, len(in))
   522  	for i := range in {
   523  		b[i] = in[i].(byte)
   524  	}
   525  	return b
   526  }