github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/src/runtime/print1.go (about) 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 = sp.str 17 rp.len = uint(sp.len) 18 rp.cap = uint(sp.len) 19 return 20 } 21 22 // printf is only called from C code. It has no type information for the args, 23 // but C stacks are ignored by the garbage collector anyway, so having 24 // type information would not add anything. 25 //go:nosplit 26 func printf(s *byte) { 27 vprintf(gostringnocopy(s), add(unsafe.Pointer(&s), unsafe.Sizeof(s))) 28 } 29 30 // sprintf is only called from C code. It has no type information for the args, 31 // but C stacks are ignored by the garbage collector anyway, so having 32 // type information would not add anything. 33 //go:nosplit 34 func snprintf(dst *byte, n int32, s *byte) { 35 buf := (*[1 << 30]byte)(unsafe.Pointer(dst))[0:n:n] 36 37 gp := getg() 38 gp.writebuf = buf[0:0 : n-1] // leave room for NUL, this is called from C 39 vprintf(gostringnocopy(s), add(unsafe.Pointer(&s), unsafe.Sizeof(s))) 40 buf[len(gp.writebuf)] = '\x00' 41 gp.writebuf = nil 42 } 43 44 var debuglock mutex 45 46 // The compiler emits calls to printlock and printunlock around 47 // the multiple calls that implement a single Go print or println 48 // statement. Some of the print helpers (printsp, for example) 49 // call print recursively. There is also the problem of a crash 50 // happening during the print routines and needing to acquire 51 // the print lock to print information about the crash. 52 // For both these reasons, let a thread acquire the printlock 'recursively'. 53 54 func printlock() { 55 mp := getg().m 56 mp.printlock++ 57 if mp.printlock == 1 { 58 lock(&debuglock) 59 } 60 } 61 62 func printunlock() { 63 mp := getg().m 64 mp.printlock-- 65 if mp.printlock == 0 { 66 unlock(&debuglock) 67 } 68 } 69 70 // write to goroutine-local buffer if diverting output, 71 // or else standard error. 72 func gwrite(b []byte) { 73 if len(b) == 0 { 74 return 75 } 76 gp := getg() 77 if gp == nil || gp.writebuf == nil { 78 write(2, unsafe.Pointer(&b[0]), int32(len(b))) 79 return 80 } 81 82 n := copy(gp.writebuf[len(gp.writebuf):cap(gp.writebuf)], b) 83 gp.writebuf = gp.writebuf[:len(gp.writebuf)+n] 84 } 85 86 func prints(s *byte) { 87 b := (*[1 << 30]byte)(unsafe.Pointer(s)) 88 for i := 0; ; i++ { 89 if b[i] == 0 { 90 gwrite(b[:i]) 91 return 92 } 93 } 94 } 95 96 func printsp() { 97 print(" ") 98 } 99 100 func printnl() { 101 print("\n") 102 } 103 104 // Very simple printf. Only for debugging prints. 105 // Do not add to this without checking with Rob. 106 func vprintf(str string, arg unsafe.Pointer) { 107 printlock() 108 109 s := bytes(str) 110 start := 0 111 i := 0 112 for ; i < len(s); i++ { 113 if s[i] != '%' { 114 continue 115 } 116 if i > start { 117 gwrite(s[start:i]) 118 } 119 if i++; i >= len(s) { 120 break 121 } 122 var siz uintptr 123 switch s[i] { 124 case 't', 'c': 125 siz = 1 126 case 'd', 'x': // 32-bit 127 arg = roundup(arg, 4) 128 siz = 4 129 case 'D', 'U', 'X', 'f': // 64-bit 130 arg = roundup(arg, unsafe.Sizeof(uintreg(0))) 131 siz = 8 132 case 'C': 133 arg = roundup(arg, unsafe.Sizeof(uintreg(0))) 134 siz = 16 135 case 'p', 's': // pointer-sized 136 arg = roundup(arg, unsafe.Sizeof(uintptr(0))) 137 siz = unsafe.Sizeof(uintptr(0)) 138 case 'S': // pointer-aligned but bigger 139 arg = roundup(arg, unsafe.Sizeof(uintptr(0))) 140 siz = unsafe.Sizeof(string("")) 141 case 'a': // pointer-aligned but bigger 142 arg = roundup(arg, unsafe.Sizeof(uintptr(0))) 143 siz = unsafe.Sizeof([]byte{}) 144 case 'i', 'e': // pointer-aligned but bigger 145 arg = roundup(arg, unsafe.Sizeof(uintptr(0))) 146 siz = unsafe.Sizeof(interface{}(nil)) 147 } 148 switch s[i] { 149 case 'a': 150 printslice(*(*[]byte)(arg)) 151 case 'c': 152 printbyte(*(*byte)(arg)) 153 case 'd': 154 printint(int64(*(*int32)(arg))) 155 case 'D': 156 printint(int64(*(*int64)(arg))) 157 case 'e': 158 printeface(*(*interface{})(arg)) 159 case 'f': 160 printfloat(*(*float64)(arg)) 161 case 'C': 162 printcomplex(*(*complex128)(arg)) 163 case 'i': 164 printiface(*(*fInterface)(arg)) 165 case 'p': 166 printpointer(*(*unsafe.Pointer)(arg)) 167 case 's': 168 prints(*(**byte)(arg)) 169 case 'S': 170 printstring(*(*string)(arg)) 171 case 't': 172 printbool(*(*bool)(arg)) 173 case 'U': 174 printuint(*(*uint64)(arg)) 175 case 'x': 176 printhex(uint64(*(*uint32)(arg))) 177 case 'X': 178 printhex(*(*uint64)(arg)) 179 } 180 arg = add(arg, siz) 181 start = i + 1 182 } 183 if start < i { 184 gwrite(s[start:i]) 185 } 186 187 printunlock() 188 } 189 190 func printpc(p unsafe.Pointer) { 191 print("PC=", hex(uintptr(p))) 192 } 193 194 func printbool(v bool) { 195 if v { 196 print("true") 197 } else { 198 print("false") 199 } 200 } 201 202 func printbyte(c byte) { 203 gwrite((*[1]byte)(unsafe.Pointer(&c))[:]) 204 } 205 206 func printfloat(v float64) { 207 switch { 208 case v != v: 209 print("NaN") 210 return 211 case v+v == v && v > 0: 212 print("+Inf") 213 return 214 case v+v == v && v < 0: 215 print("-Inf") 216 return 217 } 218 219 const n = 7 // digits printed 220 var buf [n + 7]byte 221 buf[0] = '+' 222 e := 0 // exp 223 if v == 0 { 224 if 1/v < 0 { 225 buf[0] = '-' 226 } 227 } else { 228 if v < 0 { 229 v = -v 230 buf[0] = '-' 231 } 232 233 // normalize 234 for v >= 10 { 235 e++ 236 v /= 10 237 } 238 for v < 1 { 239 e-- 240 v *= 10 241 } 242 243 // round 244 h := 5.0 245 for i := 0; i < n; i++ { 246 h /= 10 247 } 248 v += h 249 if v >= 10 { 250 e++ 251 v /= 10 252 } 253 } 254 255 // format +d.dddd+edd 256 for i := 0; i < n; i++ { 257 s := int(v) 258 buf[i+2] = byte(s + '0') 259 v -= float64(s) 260 v *= 10 261 } 262 buf[1] = buf[2] 263 buf[2] = '.' 264 265 buf[n+2] = 'e' 266 buf[n+3] = '+' 267 if e < 0 { 268 e = -e 269 buf[n+3] = '-' 270 } 271 272 buf[n+4] = byte(e/100) + '0' 273 buf[n+5] = byte(e/10)%10 + '0' 274 buf[n+6] = byte(e%10) + '0' 275 gwrite(buf[:]) 276 } 277 278 func printcomplex(c complex128) { 279 print("(", real(c), imag(c), "i)") 280 } 281 282 func printuint(v uint64) { 283 var buf [100]byte 284 i := len(buf) 285 for i--; i > 0; i-- { 286 buf[i] = byte(v%10 + '0') 287 if v < 10 { 288 break 289 } 290 v /= 10 291 } 292 gwrite(buf[i:]) 293 } 294 295 func printint(v int64) { 296 if v < 0 { 297 print("-") 298 v = -v 299 } 300 printuint(uint64(v)) 301 } 302 303 func printhex(v uint64) { 304 const dig = "0123456789abcdef" 305 var buf [100]byte 306 i := len(buf) 307 for i--; i > 0; i-- { 308 buf[i] = dig[v%16] 309 if v < 16 { 310 break 311 } 312 v /= 16 313 } 314 i-- 315 buf[i] = 'x' 316 i-- 317 buf[i] = '0' 318 gwrite(buf[i:]) 319 } 320 321 func printpointer(p unsafe.Pointer) { 322 printhex(uint64(uintptr(p))) 323 } 324 325 func printstring(s string) { 326 if uintptr(len(s)) > maxstring { 327 gwrite(bytes("[string too long]")) 328 return 329 } 330 gwrite(bytes(s)) 331 } 332 333 func printslice(s []byte) { 334 sp := (*slice)(unsafe.Pointer(&s)) 335 print("[", len(s), "/", cap(s), "]") 336 printpointer(unsafe.Pointer(sp.array)) 337 } 338 339 func printeface(e interface{}) { 340 ep := (*eface)(unsafe.Pointer(&e)) 341 print("(", ep._type, ",", ep.data, ")") 342 } 343 344 func printiface(i fInterface) { 345 ip := (*iface)(unsafe.Pointer(&i)) 346 print("(", ip.tab, ",", ip.data, ")") 347 }