github.com/jd-ly/tools@v0.5.7/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 "bytes" 12 "math" 13 "os" 14 "runtime" 15 "strings" 16 "time" 17 "unicode/utf8" 18 ) 19 20 type externalFn func(fr *frame, args []value) value 21 22 // TODO(adonovan): fix: reflect.Value abstracts an lvalue or an 23 // rvalue; Set() causes mutations that can be observed via aliases. 24 // We have not captured that correctly here. 25 26 // Key strings are from Function.String(). 27 var externals = make(map[string]externalFn) 28 29 func init() { 30 // That little dot ۰ is an Arabic zero numeral (U+06F0), categories [Nd]. 31 for k, v := range map[string]externalFn{ 32 "(reflect.Value).Bool": ext۰reflect۰Value۰Bool, 33 "(reflect.Value).CanAddr": ext۰reflect۰Value۰CanAddr, 34 "(reflect.Value).CanInterface": ext۰reflect۰Value۰CanInterface, 35 "(reflect.Value).Elem": ext۰reflect۰Value۰Elem, 36 "(reflect.Value).Field": ext۰reflect۰Value۰Field, 37 "(reflect.Value).Float": ext۰reflect۰Value۰Float, 38 "(reflect.Value).Index": ext۰reflect۰Value۰Index, 39 "(reflect.Value).Int": ext۰reflect۰Value۰Int, 40 "(reflect.Value).Interface": ext۰reflect۰Value۰Interface, 41 "(reflect.Value).IsNil": ext۰reflect۰Value۰IsNil, 42 "(reflect.Value).IsValid": ext۰reflect۰Value۰IsValid, 43 "(reflect.Value).Kind": ext۰reflect۰Value۰Kind, 44 "(reflect.Value).Len": ext۰reflect۰Value۰Len, 45 "(reflect.Value).MapIndex": ext۰reflect۰Value۰MapIndex, 46 "(reflect.Value).MapKeys": ext۰reflect۰Value۰MapKeys, 47 "(reflect.Value).NumField": ext۰reflect۰Value۰NumField, 48 "(reflect.Value).NumMethod": ext۰reflect۰Value۰NumMethod, 49 "(reflect.Value).Pointer": ext۰reflect۰Value۰Pointer, 50 "(reflect.Value).Set": ext۰reflect۰Value۰Set, 51 "(reflect.Value).String": ext۰reflect۰Value۰String, 52 "(reflect.Value).Type": ext۰reflect۰Value۰Type, 53 "(reflect.Value).Uint": ext۰reflect۰Value۰Uint, 54 "(reflect.error).Error": ext۰reflect۰error۰Error, 55 "(reflect.rtype).Bits": ext۰reflect۰rtype۰Bits, 56 "(reflect.rtype).Elem": ext۰reflect۰rtype۰Elem, 57 "(reflect.rtype).Field": ext۰reflect۰rtype۰Field, 58 "(reflect.rtype).In": ext۰reflect۰rtype۰In, 59 "(reflect.rtype).Kind": ext۰reflect۰rtype۰Kind, 60 "(reflect.rtype).NumField": ext۰reflect۰rtype۰NumField, 61 "(reflect.rtype).NumIn": ext۰reflect۰rtype۰NumIn, 62 "(reflect.rtype).NumMethod": ext۰reflect۰rtype۰NumMethod, 63 "(reflect.rtype).NumOut": ext۰reflect۰rtype۰NumOut, 64 "(reflect.rtype).Out": ext۰reflect۰rtype۰Out, 65 "(reflect.rtype).Size": ext۰reflect۰rtype۰Size, 66 "(reflect.rtype).String": ext۰reflect۰rtype۰String, 67 "bytes.Equal": ext۰bytes۰Equal, 68 "bytes.IndexByte": ext۰bytes۰IndexByte, 69 "fmt.Sprint": ext۰fmt۰Sprint, 70 "math.Abs": ext۰math۰Abs, 71 "math.Exp": ext۰math۰Exp, 72 "math.Float32bits": ext۰math۰Float32bits, 73 "math.Float32frombits": ext۰math۰Float32frombits, 74 "math.Float64bits": ext۰math۰Float64bits, 75 "math.Float64frombits": ext۰math۰Float64frombits, 76 "math.Inf": ext۰math۰Inf, 77 "math.IsNaN": ext۰math۰IsNaN, 78 "math.Ldexp": ext۰math۰Ldexp, 79 "math.Log": ext۰math۰Log, 80 "math.Min": ext۰math۰Min, 81 "math.NaN": ext۰math۰NaN, 82 "os.Exit": ext۰os۰Exit, 83 "os.Getenv": ext۰os۰Getenv, 84 "reflect.New": ext۰reflect۰New, 85 "reflect.SliceOf": ext۰reflect۰SliceOf, 86 "reflect.TypeOf": ext۰reflect۰TypeOf, 87 "reflect.ValueOf": ext۰reflect۰ValueOf, 88 "reflect.Zero": ext۰reflect۰Zero, 89 "runtime.Breakpoint": ext۰runtime۰Breakpoint, 90 "runtime.GC": ext۰runtime۰GC, 91 "runtime.GOMAXPROCS": ext۰runtime۰GOMAXPROCS, 92 "runtime.GOROOT": ext۰runtime۰GOROOT, 93 "runtime.Goexit": ext۰runtime۰Goexit, 94 "runtime.Gosched": ext۰runtime۰Gosched, 95 "runtime.NumCPU": ext۰runtime۰NumCPU, 96 "strings.Count": ext۰strings۰Count, 97 "strings.Index": ext۰strings۰Index, 98 "strings.IndexByte": ext۰strings۰IndexByte, 99 "strings.Replace": ext۰strings۰Replace, 100 "time.Sleep": ext۰time۰Sleep, 101 "unicode/utf8.DecodeRuneInString": ext۰unicode۰utf8۰DecodeRuneInString, 102 } { 103 externals[k] = v 104 } 105 } 106 107 func ext۰bytes۰Equal(fr *frame, args []value) value { 108 // func Equal(a, b []byte) bool 109 a := args[0].([]value) 110 b := args[1].([]value) 111 if len(a) != len(b) { 112 return false 113 } 114 for i := range a { 115 if a[i] != b[i] { 116 return false 117 } 118 } 119 return true 120 } 121 122 func ext۰bytes۰IndexByte(fr *frame, args []value) value { 123 // func IndexByte(s []byte, c byte) int 124 s := args[0].([]value) 125 c := args[1].(byte) 126 for i, b := range s { 127 if b.(byte) == c { 128 return i 129 } 130 } 131 return -1 132 } 133 134 func ext۰math۰Float64frombits(fr *frame, args []value) value { 135 return math.Float64frombits(args[0].(uint64)) 136 } 137 138 func ext۰math۰Float64bits(fr *frame, args []value) value { 139 return math.Float64bits(args[0].(float64)) 140 } 141 142 func ext۰math۰Float32frombits(fr *frame, args []value) value { 143 return math.Float32frombits(args[0].(uint32)) 144 } 145 146 func ext۰math۰Abs(fr *frame, args []value) value { 147 return math.Abs(args[0].(float64)) 148 } 149 150 func ext۰math۰Exp(fr *frame, args []value) value { 151 return math.Exp(args[0].(float64)) 152 } 153 154 func ext۰math۰Float32bits(fr *frame, args []value) value { 155 return math.Float32bits(args[0].(float32)) 156 } 157 158 func ext۰math۰Min(fr *frame, args []value) value { 159 return math.Min(args[0].(float64), args[1].(float64)) 160 } 161 162 func ext۰math۰NaN(fr *frame, args []value) value { 163 return math.NaN() 164 } 165 166 func ext۰math۰IsNaN(fr *frame, args []value) value { 167 return math.IsNaN(args[0].(float64)) 168 } 169 170 func ext۰math۰Inf(fr *frame, args []value) value { 171 return math.Inf(args[0].(int)) 172 } 173 174 func ext۰math۰Ldexp(fr *frame, args []value) value { 175 return math.Ldexp(args[0].(float64), args[1].(int)) 176 } 177 178 func ext۰math۰Log(fr *frame, args []value) value { 179 return math.Log(args[0].(float64)) 180 } 181 182 func ext۰runtime۰Breakpoint(fr *frame, args []value) value { 183 runtime.Breakpoint() 184 return nil 185 } 186 187 func ext۰strings۰Count(fr *frame, args []value) value { 188 return strings.Count(args[0].(string), args[1].(string)) 189 } 190 191 func ext۰strings۰IndexByte(fr *frame, args []value) value { 192 return strings.IndexByte(args[0].(string), args[1].(byte)) 193 } 194 195 func ext۰strings۰Index(fr *frame, args []value) value { 196 return strings.Index(args[0].(string), args[1].(string)) 197 } 198 199 func ext۰strings۰Replace(fr *frame, args []value) value { 200 // func Replace(s, old, new string, n int) string 201 s := args[0].(string) 202 new := args[1].(string) 203 old := args[2].(string) 204 n := args[3].(int) 205 return strings.Replace(s, old, new, n) 206 } 207 208 func ext۰runtime۰GOMAXPROCS(fr *frame, args []value) value { 209 // Ignore args[0]; don't let the interpreted program 210 // set the interpreter's GOMAXPROCS! 211 return runtime.GOMAXPROCS(0) 212 } 213 214 func ext۰runtime۰Goexit(fr *frame, args []value) value { 215 // TODO(adonovan): don't kill the interpreter's main goroutine. 216 runtime.Goexit() 217 return nil 218 } 219 220 func ext۰runtime۰GOROOT(fr *frame, args []value) value { 221 return runtime.GOROOT() 222 } 223 224 func ext۰runtime۰GC(fr *frame, args []value) value { 225 runtime.GC() 226 return nil 227 } 228 229 func ext۰runtime۰Gosched(fr *frame, args []value) value { 230 runtime.Gosched() 231 return nil 232 } 233 234 func ext۰runtime۰NumCPU(fr *frame, args []value) value { 235 return runtime.NumCPU() 236 } 237 238 func ext۰time۰Sleep(fr *frame, args []value) value { 239 time.Sleep(time.Duration(args[0].(int64))) 240 return nil 241 } 242 243 func valueToBytes(v value) []byte { 244 in := v.([]value) 245 b := make([]byte, len(in)) 246 for i := range in { 247 b[i] = in[i].(byte) 248 } 249 return b 250 } 251 252 func ext۰os۰Getenv(fr *frame, args []value) value { 253 name := args[0].(string) 254 switch name { 255 case "GOSSAINTERP": 256 return "1" 257 case "GOARCH": 258 return "amd64" 259 case "GOOS": 260 return "linux" 261 } 262 return os.Getenv(name) 263 } 264 265 func ext۰os۰Exit(fr *frame, args []value) value { 266 panic(exitPanic(args[0].(int))) 267 } 268 269 func ext۰unicode۰utf8۰DecodeRuneInString(fr *frame, args []value) value { 270 r, n := utf8.DecodeRuneInString(args[0].(string)) 271 return tuple{r, n} 272 } 273 274 // A fake function for turning an arbitrary value into a string. 275 // Handles only the cases needed by the tests. 276 // Uses same logic as 'print' built-in. 277 func ext۰fmt۰Sprint(fr *frame, args []value) value { 278 buf := new(bytes.Buffer) 279 wasStr := false 280 for i, arg := range args[0].([]value) { 281 x := arg.(iface).v 282 _, isStr := x.(string) 283 if i > 0 && !wasStr && !isStr { 284 buf.WriteByte(' ') 285 } 286 wasStr = isStr 287 buf.WriteString(toString(x)) 288 } 289 return buf.String() 290 }