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 }