123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324 |
- // Copyright 2009 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 runtime
- import "unsafe"
- // The compiler knows that a print of a value of this type
- // should use printhex instead of printuint (decimal).
- type hex uint64
- func bytes(s string) (ret []byte) {
- rp := (*slice)(unsafe.Pointer(&ret))
- sp := (*_string)(noescape(unsafe.Pointer(&s)))
- rp.array = sp.str
- rp.len = uint(sp.len)
- rp.cap = uint(sp.len)
- return
- }
- // printf is only called from C code. It has no type information for the args,
- // but C stacks are ignored by the garbage collector anyway, so having
- // type information would not add anything.
- //go:nosplit
- func printf(s *byte) {
- vprintf(gostringnocopy(s), add(unsafe.Pointer(&s), unsafe.Sizeof(s)))
- }
- // sprintf is only called from C code. It has no type information for the args,
- // but C stacks are ignored by the garbage collector anyway, so having
- // type information would not add anything.
- //go:nosplit
- func snprintf(dst *byte, n int32, s *byte) {
- buf := (*[1 << 30]byte)(unsafe.Pointer(dst))[0:n:n]
- gp := getg()
- gp.writebuf = buf[0:0 : n-1] // leave room for NUL, this is called from C
- vprintf(gostringnocopy(s), add(unsafe.Pointer(&s), unsafe.Sizeof(s)))
- buf[len(gp.writebuf)] = '\x00'
- gp.writebuf = nil
- }
- //var debuglock mutex
- // write to goroutine-local buffer if diverting output,
- // or else standard error.
- func gwrite(b []byte) {
- if len(b) == 0 {
- return
- }
- gp := getg()
- if gp == nil || gp.writebuf == nil {
- write(2, unsafe.Pointer(&b[0]), int32(len(b)))
- return
- }
- n := copy(gp.writebuf[len(gp.writebuf):cap(gp.writebuf)], b)
- gp.writebuf = gp.writebuf[:len(gp.writebuf)+n]
- }
- func prints(s *byte) {
- b := (*[1 << 30]byte)(unsafe.Pointer(s))
- for i := 0; ; i++ {
- if b[i] == 0 {
- gwrite(b[:i])
- return
- }
- }
- }
- func printsp() {
- print(" ")
- }
- func printnl() {
- print("\n")
- }
- // Very simple printf. Only for debugging prints.
- // Do not add to this without checking with Rob.
- func vprintf(str string, arg unsafe.Pointer) {
- //lock(&debuglock);
- s := bytes(str)
- start := 0
- i := 0
- for ; i < len(s); i++ {
- if s[i] != '%' {
- continue
- }
- if i > start {
- gwrite(s[start:i])
- }
- if i++; i >= len(s) {
- break
- }
- var siz uintptr
- switch s[i] {
- case 't', 'c':
- siz = 1
- case 'd', 'x': // 32-bit
- arg = roundup(arg, 4)
- siz = 4
- case 'D', 'U', 'X', 'f': // 64-bit
- arg = roundup(arg, unsafe.Sizeof(uintreg(0)))
- siz = 8
- case 'C':
- arg = roundup(arg, unsafe.Sizeof(uintreg(0)))
- siz = 16
- case 'p', 's': // pointer-sized
- arg = roundup(arg, unsafe.Sizeof(uintptr(0)))
- siz = unsafe.Sizeof(uintptr(0))
- case 'S': // pointer-aligned but bigger
- arg = roundup(arg, unsafe.Sizeof(uintptr(0)))
- siz = unsafe.Sizeof(string(""))
- case 'a': // pointer-aligned but bigger
- arg = roundup(arg, unsafe.Sizeof(uintptr(0)))
- siz = unsafe.Sizeof([]byte{})
- case 'i', 'e': // pointer-aligned but bigger
- arg = roundup(arg, unsafe.Sizeof(uintptr(0)))
- siz = unsafe.Sizeof(interface{}(nil))
- }
- switch s[i] {
- case 'a':
- printslice(*(*[]byte)(arg))
- case 'c':
- printbyte(*(*byte)(arg))
- case 'd':
- printint(int64(*(*int32)(arg)))
- case 'D':
- printint(int64(*(*int64)(arg)))
- case 'e':
- printeface(*(*interface{})(arg))
- case 'f':
- printfloat(*(*float64)(arg))
- case 'C':
- printcomplex(*(*complex128)(arg))
- case 'i':
- printiface(*(*fInterface)(arg))
- case 'p':
- printpointer(*(*unsafe.Pointer)(arg))
- case 's':
- prints(*(**byte)(arg))
- case 'S':
- printstring(*(*string)(arg))
- case 't':
- printbool(*(*bool)(arg))
- case 'U':
- printuint(*(*uint64)(arg))
- case 'x':
- printhex(uint64(*(*uint32)(arg)))
- case 'X':
- printhex(*(*uint64)(arg))
- }
- arg = add(arg, siz)
- start = i + 1
- }
- if start < i {
- gwrite(s[start:i])
- }
- //unlock(&debuglock);
- }
- func printpc(p unsafe.Pointer) {
- print("PC=", hex(uintptr(p)))
- }
- func printbool(v bool) {
- if v {
- print("true")
- } else {
- print("false")
- }
- }
- func printbyte(c byte) {
- gwrite((*[1]byte)(unsafe.Pointer(&c))[:])
- }
- func printfloat(v float64) {
- switch {
- case v != v:
- print("NaN")
- return
- case v+v == v && v > 0:
- print("+Inf")
- return
- case v+v == v && v < 0:
- print("-Inf")
- return
- }
- const n = 7 // digits printed
- var buf [n + 7]byte
- buf[0] = '+'
- e := 0 // exp
- if v == 0 {
- if 1/v < 0 {
- buf[0] = '-'
- }
- } else {
- if v < 0 {
- v = -v
- buf[0] = '-'
- }
- // normalize
- for v >= 10 {
- e++
- v /= 10
- }
- for v < 1 {
- e--
- v *= 10
- }
- // round
- h := 5.0
- for i := 0; i < n; i++ {
- h /= 10
- }
- v += h
- if v >= 10 {
- e++
- v /= 10
- }
- }
- // format +d.dddd+edd
- for i := 0; i < n; i++ {
- s := int(v)
- buf[i+2] = byte(s + '0')
- v -= float64(s)
- v *= 10
- }
- buf[1] = buf[2]
- buf[2] = '.'
- buf[n+2] = 'e'
- buf[n+3] = '+'
- if e < 0 {
- e = -e
- buf[n+3] = '-'
- }
- buf[n+4] = byte(e/100) + '0'
- buf[n+5] = byte(e/10)%10 + '0'
- buf[n+6] = byte(e%10) + '0'
- gwrite(buf[:])
- }
- func printcomplex(c complex128) {
- print("(", real(c), imag(c), "i)")
- }
- func printuint(v uint64) {
- var buf [100]byte
- i := len(buf)
- for i--; i > 0; i-- {
- buf[i] = byte(v%10 + '0')
- if v < 10 {
- break
- }
- v /= 10
- }
- gwrite(buf[i:])
- }
- func printint(v int64) {
- if v < 0 {
- print("-")
- v = -v
- }
- printuint(uint64(v))
- }
- func printhex(v uint64) {
- const dig = "0123456789abcdef"
- var buf [100]byte
- i := len(buf)
- for i--; i > 0; i-- {
- buf[i] = dig[v%16]
- if v < 16 {
- break
- }
- v /= 16
- }
- i--
- buf[i] = 'x'
- i--
- buf[i] = '0'
- gwrite(buf[i:])
- }
- func printpointer(p unsafe.Pointer) {
- printhex(uint64(uintptr(p)))
- }
- func printstring(s string) {
- if uintptr(len(s)) > maxstring {
- gwrite(bytes("[string too long]"))
- return
- }
- gwrite(bytes(s))
- }
- func printslice(s []byte) {
- sp := (*slice)(unsafe.Pointer(&s))
- print("[", len(s), "/", cap(s), "]")
- printpointer(unsafe.Pointer(sp.array))
- }
- func printeface(e interface{}) {
- ep := (*eface)(unsafe.Pointer(&e))
- print("(", ep._type, ",", ep.data, ")")
- }
- func printiface(i fInterface) {
- ip := (*iface)(unsafe.Pointer(&i))
- print("(", ip.tab, ",", ip.data, ")")
- }
|