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