484 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			484 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 functions that we cannot interpret because they are
 | 
						||
// external or because they use "unsafe" or "reflect" operations.
 | 
						||
 | 
						||
import (
 | 
						||
	"math"
 | 
						||
	"os"
 | 
						||
	"runtime"
 | 
						||
	"syscall"
 | 
						||
	"time"
 | 
						||
	"unsafe"
 | 
						||
 | 
						||
	"llvm.org/llgo/third_party/gotools/go/ssa"
 | 
						||
	"llvm.org/llgo/third_party/gotools/go/types"
 | 
						||
)
 | 
						||
 | 
						||
type externalFn func(fr *frame, args []value) value
 | 
						||
 | 
						||
// TODO(adonovan): fix: reflect.Value abstracts an lvalue or an
 | 
						||
// rvalue; Set() causes mutations that can be observed via aliases.
 | 
						||
// We have not captured that correctly here.
 | 
						||
 | 
						||
// Key strings are from Function.String().
 | 
						||
var externals map[string]externalFn
 | 
						||
 | 
						||
func init() {
 | 
						||
	// That little dot ۰ is an Arabic zero numeral (U+06F0), categories [Nd].
 | 
						||
	externals = map[string]externalFn{
 | 
						||
		"(*sync.Pool).Get":                 ext۰sync۰Pool۰Get,
 | 
						||
		"(*sync.Pool).Put":                 ext۰sync۰Pool۰Put,
 | 
						||
		"(reflect.Value).Bool":             ext۰reflect۰Value۰Bool,
 | 
						||
		"(reflect.Value).CanAddr":          ext۰reflect۰Value۰CanAddr,
 | 
						||
		"(reflect.Value).CanInterface":     ext۰reflect۰Value۰CanInterface,
 | 
						||
		"(reflect.Value).Elem":             ext۰reflect۰Value۰Elem,
 | 
						||
		"(reflect.Value).Field":            ext۰reflect۰Value۰Field,
 | 
						||
		"(reflect.Value).Float":            ext۰reflect۰Value۰Float,
 | 
						||
		"(reflect.Value).Index":            ext۰reflect۰Value۰Index,
 | 
						||
		"(reflect.Value).Int":              ext۰reflect۰Value۰Int,
 | 
						||
		"(reflect.Value).Interface":        ext۰reflect۰Value۰Interface,
 | 
						||
		"(reflect.Value).IsNil":            ext۰reflect۰Value۰IsNil,
 | 
						||
		"(reflect.Value).IsValid":          ext۰reflect۰Value۰IsValid,
 | 
						||
		"(reflect.Value).Kind":             ext۰reflect۰Value۰Kind,
 | 
						||
		"(reflect.Value).Len":              ext۰reflect۰Value۰Len,
 | 
						||
		"(reflect.Value).MapIndex":         ext۰reflect۰Value۰MapIndex,
 | 
						||
		"(reflect.Value).MapKeys":          ext۰reflect۰Value۰MapKeys,
 | 
						||
		"(reflect.Value).NumField":         ext۰reflect۰Value۰NumField,
 | 
						||
		"(reflect.Value).NumMethod":        ext۰reflect۰Value۰NumMethod,
 | 
						||
		"(reflect.Value).Pointer":          ext۰reflect۰Value۰Pointer,
 | 
						||
		"(reflect.Value).Set":              ext۰reflect۰Value۰Set,
 | 
						||
		"(reflect.Value).String":           ext۰reflect۰Value۰String,
 | 
						||
		"(reflect.Value).Type":             ext۰reflect۰Value۰Type,
 | 
						||
		"(reflect.Value).Uint":             ext۰reflect۰Value۰Uint,
 | 
						||
		"(reflect.error).Error":            ext۰reflect۰error۰Error,
 | 
						||
		"(reflect.rtype).Bits":             ext۰reflect۰rtype۰Bits,
 | 
						||
		"(reflect.rtype).Elem":             ext۰reflect۰rtype۰Elem,
 | 
						||
		"(reflect.rtype).Field":            ext۰reflect۰rtype۰Field,
 | 
						||
		"(reflect.rtype).Kind":             ext۰reflect۰rtype۰Kind,
 | 
						||
		"(reflect.rtype).NumField":         ext۰reflect۰rtype۰NumField,
 | 
						||
		"(reflect.rtype).NumMethod":        ext۰reflect۰rtype۰NumMethod,
 | 
						||
		"(reflect.rtype).NumOut":           ext۰reflect۰rtype۰NumOut,
 | 
						||
		"(reflect.rtype).Out":              ext۰reflect۰rtype۰Out,
 | 
						||
		"(reflect.rtype).Size":             ext۰reflect۰rtype۰Size,
 | 
						||
		"(reflect.rtype).String":           ext۰reflect۰rtype۰String,
 | 
						||
		"bytes.Equal":                      ext۰bytes۰Equal,
 | 
						||
		"bytes.IndexByte":                  ext۰bytes۰IndexByte,
 | 
						||
		"hash/crc32.haveSSE42":             ext۰crc32۰haveSSE42,
 | 
						||
		"math.Abs":                         ext۰math۰Abs,
 | 
						||
		"math.Exp":                         ext۰math۰Exp,
 | 
						||
		"math.Float32bits":                 ext۰math۰Float32bits,
 | 
						||
		"math.Float32frombits":             ext۰math۰Float32frombits,
 | 
						||
		"math.Float64bits":                 ext۰math۰Float64bits,
 | 
						||
		"math.Float64frombits":             ext۰math۰Float64frombits,
 | 
						||
		"math.Ldexp":                       ext۰math۰Ldexp,
 | 
						||
		"math.Log":                         ext۰math۰Log,
 | 
						||
		"math.Min":                         ext۰math۰Min,
 | 
						||
		"os.runtime_args":                  ext۰os۰runtime_args,
 | 
						||
		"reflect.New":                      ext۰reflect۰New,
 | 
						||
		"reflect.SliceOf":                  ext۰reflect۰SliceOf,
 | 
						||
		"reflect.TypeOf":                   ext۰reflect۰TypeOf,
 | 
						||
		"reflect.ValueOf":                  ext۰reflect۰ValueOf,
 | 
						||
		"reflect.init":                     ext۰reflect۰Init,
 | 
						||
		"reflect.valueInterface":           ext۰reflect۰valueInterface,
 | 
						||
		"runtime.Breakpoint":               ext۰runtime۰Breakpoint,
 | 
						||
		"runtime.Caller":                   ext۰runtime۰Caller,
 | 
						||
		"runtime.Callers":                  ext۰runtime۰Callers,
 | 
						||
		"runtime.FuncForPC":                ext۰runtime۰FuncForPC,
 | 
						||
		"runtime.GC":                       ext۰runtime۰GC,
 | 
						||
		"runtime.GOMAXPROCS":               ext۰runtime۰GOMAXPROCS,
 | 
						||
		"runtime.Goexit":                   ext۰runtime۰Goexit,
 | 
						||
		"runtime.Gosched":                  ext۰runtime۰Gosched,
 | 
						||
		"runtime.init":                     ext۰runtime۰init,
 | 
						||
		"runtime.NumCPU":                   ext۰runtime۰NumCPU,
 | 
						||
		"runtime.ReadMemStats":             ext۰runtime۰ReadMemStats,
 | 
						||
		"runtime.SetFinalizer":             ext۰runtime۰SetFinalizer,
 | 
						||
		"(*runtime.Func).Entry":            ext۰runtime۰Func۰Entry,
 | 
						||
		"(*runtime.Func).FileLine":         ext۰runtime۰Func۰FileLine,
 | 
						||
		"(*runtime.Func).Name":             ext۰runtime۰Func۰Name,
 | 
						||
		"runtime.environ":                  ext۰runtime۰environ,
 | 
						||
		"runtime.getgoroot":                ext۰runtime۰getgoroot,
 | 
						||
		"strings.IndexByte":                ext۰strings۰IndexByte,
 | 
						||
		"sync.runtime_Semacquire":          ext۰sync۰runtime_Semacquire,
 | 
						||
		"sync.runtime_Semrelease":          ext۰sync۰runtime_Semrelease,
 | 
						||
		"sync.runtime_Syncsemcheck":        ext۰sync۰runtime_Syncsemcheck,
 | 
						||
		"sync.runtime_registerPoolCleanup": ext۰sync۰runtime_registerPoolCleanup,
 | 
						||
		"sync/atomic.AddInt32":             ext۰atomic۰AddInt32,
 | 
						||
		"sync/atomic.AddUint32":            ext۰atomic۰AddUint32,
 | 
						||
		"sync/atomic.AddUint64":            ext۰atomic۰AddUint64,
 | 
						||
		"sync/atomic.CompareAndSwapInt32":  ext۰atomic۰CompareAndSwapInt32,
 | 
						||
		"sync/atomic.LoadInt32":            ext۰atomic۰LoadInt32,
 | 
						||
		"sync/atomic.LoadUint32":           ext۰atomic۰LoadUint32,
 | 
						||
		"sync/atomic.StoreInt32":           ext۰atomic۰StoreInt32,
 | 
						||
		"sync/atomic.StoreUint32":          ext۰atomic۰StoreUint32,
 | 
						||
		"syscall.Close":                    ext۰syscall۰Close,
 | 
						||
		"syscall.Exit":                     ext۰syscall۰Exit,
 | 
						||
		"syscall.Fstat":                    ext۰syscall۰Fstat,
 | 
						||
		"syscall.Getpid":                   ext۰syscall۰Getpid,
 | 
						||
		"syscall.Getwd":                    ext۰syscall۰Getwd,
 | 
						||
		"syscall.Kill":                     ext۰syscall۰Kill,
 | 
						||
		"syscall.Lstat":                    ext۰syscall۰Lstat,
 | 
						||
		"syscall.Open":                     ext۰syscall۰Open,
 | 
						||
		"syscall.ParseDirent":              ext۰syscall۰ParseDirent,
 | 
						||
		"syscall.RawSyscall":               ext۰syscall۰RawSyscall,
 | 
						||
		"syscall.Read":                     ext۰syscall۰Read,
 | 
						||
		"syscall.ReadDirent":               ext۰syscall۰ReadDirent,
 | 
						||
		"syscall.Stat":                     ext۰syscall۰Stat,
 | 
						||
		"syscall.Write":                    ext۰syscall۰Write,
 | 
						||
		"syscall.runtime_envs":             ext۰runtime۰environ,
 | 
						||
		"time.Sleep":                       ext۰time۰Sleep,
 | 
						||
		"time.now":                         ext۰time۰now,
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
// wrapError returns an interpreted 'error' interface value for err.
 | 
						||
func wrapError(err error) value {
 | 
						||
	if err == nil {
 | 
						||
		return iface{}
 | 
						||
	}
 | 
						||
	return iface{t: errorType, v: err.Error()}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰sync۰Pool۰Get(fr *frame, args []value) value {
 | 
						||
	Pool := fr.i.prog.ImportedPackage("sync").Type("Pool").Object()
 | 
						||
	_, newIndex, _ := types.LookupFieldOrMethod(Pool.Type(), false, Pool.Pkg(), "New")
 | 
						||
 | 
						||
	if New := (*args[0].(*value)).(structure)[newIndex[0]]; New != nil {
 | 
						||
		return call(fr.i, fr, 0, New, nil)
 | 
						||
	}
 | 
						||
	return nil
 | 
						||
}
 | 
						||
 | 
						||
func ext۰sync۰Pool۰Put(fr *frame, args []value) value {
 | 
						||
	return nil
 | 
						||
}
 | 
						||
 | 
						||
func ext۰bytes۰Equal(fr *frame, args []value) value {
 | 
						||
	// func Equal(a, b []byte) bool
 | 
						||
	a := args[0].([]value)
 | 
						||
	b := args[1].([]value)
 | 
						||
	if len(a) != len(b) {
 | 
						||
		return false
 | 
						||
	}
 | 
						||
	for i := range a {
 | 
						||
		if a[i] != b[i] {
 | 
						||
			return false
 | 
						||
		}
 | 
						||
	}
 | 
						||
	return true
 | 
						||
}
 | 
						||
 | 
						||
func ext۰bytes۰IndexByte(fr *frame, args []value) value {
 | 
						||
	// func IndexByte(s []byte, c byte) int
 | 
						||
	s := args[0].([]value)
 | 
						||
	c := args[1].(byte)
 | 
						||
	for i, b := range s {
 | 
						||
		if b.(byte) == c {
 | 
						||
			return i
 | 
						||
		}
 | 
						||
	}
 | 
						||
	return -1
 | 
						||
}
 | 
						||
 | 
						||
func ext۰crc32۰haveSSE42(fr *frame, args []value) value {
 | 
						||
	return false
 | 
						||
}
 | 
						||
 | 
						||
func ext۰math۰Float64frombits(fr *frame, args []value) value {
 | 
						||
	return math.Float64frombits(args[0].(uint64))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰math۰Float64bits(fr *frame, args []value) value {
 | 
						||
	return math.Float64bits(args[0].(float64))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰math۰Float32frombits(fr *frame, args []value) value {
 | 
						||
	return math.Float32frombits(args[0].(uint32))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰math۰Abs(fr *frame, args []value) value {
 | 
						||
	return math.Abs(args[0].(float64))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰math۰Exp(fr *frame, args []value) value {
 | 
						||
	return math.Exp(args[0].(float64))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰math۰Float32bits(fr *frame, args []value) value {
 | 
						||
	return math.Float32bits(args[0].(float32))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰math۰Min(fr *frame, args []value) value {
 | 
						||
	return math.Min(args[0].(float64), args[1].(float64))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰math۰Ldexp(fr *frame, args []value) value {
 | 
						||
	return math.Ldexp(args[0].(float64), args[1].(int))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰math۰Log(fr *frame, args []value) value {
 | 
						||
	return math.Log(args[0].(float64))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰os۰runtime_args(fr *frame, args []value) value {
 | 
						||
	return fr.i.osArgs
 | 
						||
}
 | 
						||
 | 
						||
func ext۰runtime۰Breakpoint(fr *frame, args []value) value {
 | 
						||
	runtime.Breakpoint()
 | 
						||
	return nil
 | 
						||
}
 | 
						||
 | 
						||
func ext۰runtime۰Caller(fr *frame, args []value) value {
 | 
						||
	// func Caller(skip int) (pc uintptr, file string, line int, ok bool)
 | 
						||
	skip := 1 + args[0].(int)
 | 
						||
	for i := 0; i < skip; i++ {
 | 
						||
		if fr != nil {
 | 
						||
			fr = fr.caller
 | 
						||
		}
 | 
						||
	}
 | 
						||
	var pc uintptr
 | 
						||
	var file string
 | 
						||
	var line int
 | 
						||
	var ok bool
 | 
						||
	if fr != nil {
 | 
						||
		fn := fr.fn
 | 
						||
		// TODO(adonovan): use pc/posn of current instruction, not start of fn.
 | 
						||
		pc = uintptr(unsafe.Pointer(fn))
 | 
						||
		posn := fn.Prog.Fset.Position(fn.Pos())
 | 
						||
		file = posn.Filename
 | 
						||
		line = posn.Line
 | 
						||
		ok = true
 | 
						||
	}
 | 
						||
	return tuple{pc, file, line, ok}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰runtime۰Callers(fr *frame, args []value) value {
 | 
						||
	// Callers(skip int, pc []uintptr) int
 | 
						||
	skip := args[0].(int)
 | 
						||
	pc := args[1].([]value)
 | 
						||
	for i := 0; i < skip; i++ {
 | 
						||
		if fr != nil {
 | 
						||
			fr = fr.caller
 | 
						||
		}
 | 
						||
	}
 | 
						||
	i := 0
 | 
						||
	for fr != nil {
 | 
						||
		pc[i] = uintptr(unsafe.Pointer(fr.fn))
 | 
						||
		i++
 | 
						||
		fr = fr.caller
 | 
						||
	}
 | 
						||
	return i
 | 
						||
}
 | 
						||
 | 
						||
func ext۰runtime۰FuncForPC(fr *frame, args []value) value {
 | 
						||
	// FuncForPC(pc uintptr) *Func
 | 
						||
	pc := args[0].(uintptr)
 | 
						||
	var fn *ssa.Function
 | 
						||
	if pc != 0 {
 | 
						||
		fn = (*ssa.Function)(unsafe.Pointer(pc)) // indeed unsafe!
 | 
						||
	}
 | 
						||
	var Func value
 | 
						||
	Func = structure{fn} // a runtime.Func
 | 
						||
	return &Func
 | 
						||
}
 | 
						||
 | 
						||
func ext۰runtime۰environ(fr *frame, args []value) value {
 | 
						||
	// This function also implements syscall.runtime_envs.
 | 
						||
	return environ
 | 
						||
}
 | 
						||
 | 
						||
func ext۰runtime۰getgoroot(fr *frame, args []value) value {
 | 
						||
	return os.Getenv("GOROOT")
 | 
						||
}
 | 
						||
 | 
						||
func ext۰strings۰IndexByte(fr *frame, args []value) value {
 | 
						||
	// func IndexByte(s string, c byte) int
 | 
						||
	s := args[0].(string)
 | 
						||
	c := args[1].(byte)
 | 
						||
	for i := 0; i < len(s); i++ {
 | 
						||
		if s[i] == c {
 | 
						||
			return i
 | 
						||
		}
 | 
						||
	}
 | 
						||
	return -1
 | 
						||
}
 | 
						||
 | 
						||
func ext۰sync۰runtime_Syncsemcheck(fr *frame, args []value) value {
 | 
						||
	// TODO(adonovan): fix: implement.
 | 
						||
	return nil
 | 
						||
}
 | 
						||
 | 
						||
func ext۰sync۰runtime_registerPoolCleanup(fr *frame, args []value) value {
 | 
						||
	return nil
 | 
						||
}
 | 
						||
 | 
						||
func ext۰sync۰runtime_Semacquire(fr *frame, args []value) value {
 | 
						||
	// TODO(adonovan): fix: implement.
 | 
						||
	return nil
 | 
						||
}
 | 
						||
 | 
						||
func ext۰sync۰runtime_Semrelease(fr *frame, args []value) value {
 | 
						||
	// TODO(adonovan): fix: implement.
 | 
						||
	return nil
 | 
						||
}
 | 
						||
 | 
						||
func ext۰runtime۰GOMAXPROCS(fr *frame, args []value) value {
 | 
						||
	return runtime.GOMAXPROCS(args[0].(int))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰runtime۰Goexit(fr *frame, args []value) value {
 | 
						||
	// TODO(adonovan): don't kill the interpreter's main goroutine.
 | 
						||
	runtime.Goexit()
 | 
						||
	return nil
 | 
						||
}
 | 
						||
 | 
						||
func ext۰runtime۰GC(fr *frame, args []value) value {
 | 
						||
	runtime.GC()
 | 
						||
	return nil
 | 
						||
}
 | 
						||
 | 
						||
func ext۰runtime۰Gosched(fr *frame, args []value) value {
 | 
						||
	runtime.Gosched()
 | 
						||
	return nil
 | 
						||
}
 | 
						||
 | 
						||
func ext۰runtime۰init(fr *frame, args []value) value {
 | 
						||
	return nil
 | 
						||
}
 | 
						||
 | 
						||
func ext۰runtime۰NumCPU(fr *frame, args []value) value {
 | 
						||
	return runtime.NumCPU()
 | 
						||
}
 | 
						||
 | 
						||
func ext۰runtime۰ReadMemStats(fr *frame, args []value) value {
 | 
						||
	// TODO(adonovan): populate args[0].(Struct)
 | 
						||
	return nil
 | 
						||
}
 | 
						||
 | 
						||
func ext۰atomic۰LoadUint32(fr *frame, args []value) value {
 | 
						||
	// TODO(adonovan): fix: not atomic!
 | 
						||
	return (*args[0].(*value)).(uint32)
 | 
						||
}
 | 
						||
 | 
						||
func ext۰atomic۰StoreUint32(fr *frame, args []value) value {
 | 
						||
	// TODO(adonovan): fix: not atomic!
 | 
						||
	*args[0].(*value) = args[1].(uint32)
 | 
						||
	return nil
 | 
						||
}
 | 
						||
 | 
						||
func ext۰atomic۰LoadInt32(fr *frame, args []value) value {
 | 
						||
	// TODO(adonovan): fix: not atomic!
 | 
						||
	return (*args[0].(*value)).(int32)
 | 
						||
}
 | 
						||
 | 
						||
func ext۰atomic۰StoreInt32(fr *frame, args []value) value {
 | 
						||
	// TODO(adonovan): fix: not atomic!
 | 
						||
	*args[0].(*value) = args[1].(int32)
 | 
						||
	return nil
 | 
						||
}
 | 
						||
 | 
						||
func ext۰atomic۰CompareAndSwapInt32(fr *frame, args []value) value {
 | 
						||
	// TODO(adonovan): fix: not atomic!
 | 
						||
	p := args[0].(*value)
 | 
						||
	if (*p).(int32) == args[1].(int32) {
 | 
						||
		*p = args[2].(int32)
 | 
						||
		return true
 | 
						||
	}
 | 
						||
	return false
 | 
						||
}
 | 
						||
 | 
						||
func ext۰atomic۰AddInt32(fr *frame, args []value) value {
 | 
						||
	// TODO(adonovan): fix: not atomic!
 | 
						||
	p := args[0].(*value)
 | 
						||
	newv := (*p).(int32) + args[1].(int32)
 | 
						||
	*p = newv
 | 
						||
	return newv
 | 
						||
}
 | 
						||
 | 
						||
func ext۰atomic۰AddUint32(fr *frame, args []value) value {
 | 
						||
	// TODO(adonovan): fix: not atomic!
 | 
						||
	p := args[0].(*value)
 | 
						||
	newv := (*p).(uint32) + args[1].(uint32)
 | 
						||
	*p = newv
 | 
						||
	return newv
 | 
						||
}
 | 
						||
 | 
						||
func ext۰atomic۰AddUint64(fr *frame, args []value) value {
 | 
						||
	// TODO(adonovan): fix: not atomic!
 | 
						||
	p := args[0].(*value)
 | 
						||
	newv := (*p).(uint64) + args[1].(uint64)
 | 
						||
	*p = newv
 | 
						||
	return newv
 | 
						||
}
 | 
						||
 | 
						||
func ext۰runtime۰SetFinalizer(fr *frame, args []value) value {
 | 
						||
	return nil // ignore
 | 
						||
}
 | 
						||
 | 
						||
// Pretend: type runtime.Func struct { entry *ssa.Function }
 | 
						||
 | 
						||
func ext۰runtime۰Func۰FileLine(fr *frame, args []value) value {
 | 
						||
	// func (*runtime.Func) FileLine(uintptr) (string, int)
 | 
						||
	f, _ := (*args[0].(*value)).(structure)[0].(*ssa.Function)
 | 
						||
	pc := args[1].(uintptr)
 | 
						||
	_ = pc
 | 
						||
	if f != nil {
 | 
						||
		// TODO(adonovan): use position of current instruction, not fn.
 | 
						||
		posn := f.Prog.Fset.Position(f.Pos())
 | 
						||
		return tuple{posn.Filename, posn.Line}
 | 
						||
	}
 | 
						||
	return tuple{"", 0}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰runtime۰Func۰Name(fr *frame, args []value) value {
 | 
						||
	// func (*runtime.Func) Name() string
 | 
						||
	f, _ := (*args[0].(*value)).(structure)[0].(*ssa.Function)
 | 
						||
	if f != nil {
 | 
						||
		return f.String()
 | 
						||
	}
 | 
						||
	return ""
 | 
						||
}
 | 
						||
 | 
						||
func ext۰runtime۰Func۰Entry(fr *frame, args []value) value {
 | 
						||
	// func (*runtime.Func) Entry() uintptr
 | 
						||
	f, _ := (*args[0].(*value)).(structure)[0].(*ssa.Function)
 | 
						||
	return uintptr(unsafe.Pointer(f))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰time۰now(fr *frame, args []value) value {
 | 
						||
	nano := time.Now().UnixNano()
 | 
						||
	return tuple{int64(nano / 1e9), int32(nano % 1e9)}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰time۰Sleep(fr *frame, args []value) value {
 | 
						||
	time.Sleep(time.Duration(args[0].(int64)))
 | 
						||
	return nil
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Exit(fr *frame, args []value) value {
 | 
						||
	panic(exitPanic(args[0].(int)))
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Getwd(fr *frame, args []value) value {
 | 
						||
	s, err := syscall.Getwd()
 | 
						||
	return tuple{s, wrapError(err)}
 | 
						||
}
 | 
						||
 | 
						||
func ext۰syscall۰Getpid(fr *frame, args []value) value {
 | 
						||
	return syscall.Getpid()
 | 
						||
}
 | 
						||
 | 
						||
func valueToBytes(v value) []byte {
 | 
						||
	in := v.([]value)
 | 
						||
	b := make([]byte, len(in))
 | 
						||
	for i := range in {
 | 
						||
		b[i] = in[i].(byte)
 | 
						||
	}
 | 
						||
	return b
 | 
						||
}
 |