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