blob: ba5799182a114635ea1c77586f2b334524a1ef9e [file] [log] [blame]
Russ Cox597b2662014-08-28 23:26:40 -04001// 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
5package runtime
6
7import "unsafe"
8
Russ Cox4af796f2014-08-29 13:22:17 -04009// The compiler knows that a print of a value of this type
10// should use printhex instead of printuint (decimal).
11type hex uint64
12
Russ Cox597b2662014-08-28 23:26:40 -040013func 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
Russ Cox75d3f622014-11-05 14:42:54 -050022var 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
32func printlock() {
33 mp := getg().m
Russ Coxbfeda912015-01-14 14:57:10 -050034 mp.locks++ // do not reschedule between printlock++ and lock(&debuglock).
Russ Cox75d3f622014-11-05 14:42:54 -050035 mp.printlock++
36 if mp.printlock == 1 {
37 lock(&debuglock)
38 }
Russ Coxbfeda912015-01-14 14:57:10 -050039 mp.locks-- // now we know debuglock is held and holding up mp.locks for us.
Russ Cox75d3f622014-11-05 14:42:54 -050040}
41
42func printunlock() {
43 mp := getg().m
44 mp.printlock--
45 if mp.printlock == 0 {
46 unlock(&debuglock)
47 }
48}
Russ Cox597b2662014-08-28 23:26:40 -040049
50// write to goroutine-local buffer if diverting output,
51// or else standard error.
52func gwrite(b []byte) {
53 if len(b) == 0 {
54 return
55 }
56 gp := getg()
57 if gp == nil || gp.writebuf == nil {
David Crawshawbee8ae12014-12-10 09:29:24 -050058 writeErr(b)
Russ Cox597b2662014-08-28 23:26:40 -040059 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
Russ Cox597b2662014-08-28 23:26:40 -040066func printsp() {
67 print(" ")
68}
69
70func printnl() {
71 print("\n")
72}
73
Russ Cox597b2662014-08-28 23:26:40 -040074func printpc(p unsafe.Pointer) {
Russ Cox4af796f2014-08-29 13:22:17 -040075 print("PC=", hex(uintptr(p)))
Russ Cox597b2662014-08-28 23:26:40 -040076}
77
78func printbool(v bool) {
79 if v {
80 print("true")
81 } else {
82 print("false")
83 }
84}
85
86func printbyte(c byte) {
87 gwrite((*[1]byte)(unsafe.Pointer(&c))[:])
88}
89
90func 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
162func printcomplex(c complex128) {
163 print("(", real(c), imag(c), "i)")
164}
165
166func 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
179func printint(v int64) {
180 if v < 0 {
181 print("-")
182 v = -v
183 }
184 printuint(uint64(v))
185}
186
187func 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
205func printpointer(p unsafe.Pointer) {
206 printhex(uint64(uintptr(p)))
207}
208
209func printstring(s string) {
210 if uintptr(len(s)) > maxstring {
211 gwrite(bytes("[string too long]"))
212 return
213 }
214 gwrite(bytes(s))
215}
216
217func printslice(s []byte) {
218 sp := (*slice)(unsafe.Pointer(&s))
219 print("[", len(s), "/", cap(s), "]")
220 printpointer(unsafe.Pointer(sp.array))
221}
222
223func printeface(e interface{}) {
224 ep := (*eface)(unsafe.Pointer(&e))
225 print("(", ep._type, ",", ep.data, ")")
226}
227
228func printiface(i fInterface) {
229 ip := (*iface)(unsafe.Pointer(&i))
230 print("(", ip.tab, ",", ip.data, ")")
231}