1 // Copyright 2009 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 runtime 6 7 import "unsafe" 8 9 // The compiler knows that a print of a value of this type 10 // should use printhex instead of printuint (decimal). 11 type hex uint64 12 13 func bytes(s string) (ret []byte) { 14 rp := (*slice)(unsafe.Pointer(&ret)) 15 sp := (*_string)(noescape(unsafe.Pointer(&s))) 16 rp.array = unsafe.Pointer(sp.str) 17 rp.len = sp.len 18 rp.cap = sp.len 19 return 20 } 21 22 var debuglock mutex 23 24 // The compiler emits calls to printlock and printunlock around 25 // the multiple calls that implement a single Go print or println 26 // statement. Some of the print helpers (printsp, for example) 27 // call print recursively. There is also the problem of a crash 28 // happening during the print routines and needing to acquire 29 // the print lock to print information about the crash. 30 // For both these reasons, let a thread acquire the printlock 'recursively'. 31 32 func printlock() { 33 mp := getg().m 34 mp.locks++ // do not reschedule between printlock++ and lock(&debuglock). 35 mp.printlock++ 36 if mp.printlock == 1 { 37 lock(&debuglock) 38 } 39 mp.locks-- // now we know debuglock is held and holding up mp.locks for us. 40 } 41 42 func printunlock() { 43 mp := getg().m 44 mp.printlock-- 45 if mp.printlock == 0 { 46 unlock(&debuglock) 47 } 48 } 49 50 // write to goroutine-local buffer if diverting output, 51 // or else standard error. 52 func gwrite(b []byte) { 53 if len(b) == 0 { 54 return 55 } 56 gp := getg() 57 if gp == nil || gp.writebuf == nil { 58 writeErr(b) 59 return 60 } 61 62 n := copy(gp.writebuf[len(gp.writebuf):cap(gp.writebuf)], b) 63 gp.writebuf = gp.writebuf[:len(gp.writebuf)+n] 64 } 65 66 func printsp() { 67 print(" ") 68 } 69 70 func printnl() { 71 print("\n") 72 } 73 74 func printpc(p unsafe.Pointer) { 75 print("PC=", hex(uintptr(p))) 76 } 77 78 func printbool(v bool) { 79 if v { 80 print("true") 81 } else { 82 print("false") 83 } 84 } 85 86 func printbyte(c byte) { 87 gwrite((*[1]byte)(unsafe.Pointer(&c))[:]) 88 } 89 90 func printfloat(v float64) { 91 switch { 92 case v != v: 93 print("NaN") 94 return 95 case v+v == v && v > 0: 96 print("+Inf") 97 return 98 case v+v == v && v < 0: 99 print("-Inf") 100 return 101 } 102 103 const n = 7 // digits printed 104 var buf [n + 7]byte 105 buf[0] = '+' 106 e := 0 // exp 107 if v == 0 { 108 if 1/v < 0 { 109 buf[0] = '-' 110 } 111 } else { 112 if v < 0 { 113 v = -v 114 buf[0] = '-' 115 } 116 117 // normalize 118 for v >= 10 { 119 e++ 120 v /= 10 121 } 122 for v < 1 { 123 e-- 124 v *= 10 125 } 126 127 // round 128 h := 5.0 129 for i := 0; i < n; i++ { 130 h /= 10 131 } 132 v += h 133 if v >= 10 { 134 e++ 135 v /= 10 136 } 137 } 138 139 // format +d.dddd+edd 140 for i := 0; i < n; i++ { 141 s := int(v) 142 buf[i+2] = byte(s + '0') 143 v -= float64(s) 144 v *= 10 145 } 146 buf[1] = buf[2] 147 buf[2] = '.' 148 149 buf[n+2] = 'e' 150 buf[n+3] = '+' 151 if e < 0 { 152 e = -e 153 buf[n+3] = '-' 154 } 155 156 buf[n+4] = byte(e/100) + '0' 157 buf[n+5] = byte(e/10)%10 + '0' 158 buf[n+6] = byte(e%10) + '0' 159 gwrite(buf[:]) 160 } 161 162 func printcomplex(c complex128) { 163 print("(", real(c), imag(c), "i)") 164 } 165 166 func printuint(v uint64) { 167 var buf [100]byte 168 i := len(buf) 169 for i--; i > 0; i-- { 170 buf[i] = byte(v%10 + '0') 171 if v < 10 { 172 break 173 } 174 v /= 10 175 } 176 gwrite(buf[i:]) 177 } 178 179 func printint(v int64) { 180 if v < 0 { 181 print("-") 182 v = -v 183 } 184 printuint(uint64(v)) 185 } 186 187 func printhex(v uint64) { 188 const dig = "0123456789abcdef" 189 var buf [100]byte 190 i := len(buf) 191 for i--; i > 0; i-- { 192 buf[i] = dig[v%16] 193 if v < 16 { 194 break 195 } 196 v /= 16 197 } 198 i-- 199 buf[i] = 'x' 200 i-- 201 buf[i] = '0' 202 gwrite(buf[i:]) 203 } 204 205 func printpointer(p unsafe.Pointer) { 206 printhex(uint64(uintptr(p))) 207 } 208 209 func printstring(s string) { 210 if uintptr(len(s)) > maxstring { 211 gwrite(bytes("[string too long]")) 212 return 213 } 214 gwrite(bytes(s)) 215 } 216 217 func printslice(s []byte) { 218 sp := (*slice)(unsafe.Pointer(&s)) 219 print("[", len(s), "/", cap(s), "]") 220 printpointer(unsafe.Pointer(sp.array)) 221 } 222 223 func printeface(e interface{}) { 224 ep := (*eface)(unsafe.Pointer(&e)) 225 print("(", ep._type, ",", ep.data, ")") 226 } 227 228 func printiface(i fInterface) { 229 ip := (*iface)(unsafe.Pointer(&i)) 230 print("(", ip.tab, ",", ip.data, ")") 231 } 232