github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/tools/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 // +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 "go/types" 14 "math" 15 "os" 16 "runtime" 17 "strings" 18 "syscall" 19 "time" 20 "unsafe" 21 22 "golang.org/x/tools/go/ssa" 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 }