Revert "[PATCH 7/7] RISC-V: Disable by pieces for vector setmem length > UNITS_PER_WORD"
[official-gcc.git] / libgo / go / runtime / print.go
blob8dd8bf3cd7becedb431c6e84a1ca7a7761cae68f
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.
5 package runtime
7 import (
8 "internal/goarch"
9 "runtime/internal/atomic"
10 "unsafe"
13 // For gccgo, use go:linkname to export compiler-called functions.
15 //go:linkname printbool
16 //go:linkname printfloat
17 //go:linkname printint
18 //go:linkname printhex
19 //go:linkname printuint
20 //go:linkname printcomplex
21 //go:linkname printstring
22 //go:linkname printpointer
23 //go:linkname printiface
24 //go:linkname printeface
25 //go:linkname printslice
26 //go:linkname printnl
27 //go:linkname printsp
28 //go:linkname printlock
29 //go:linkname printunlock
30 // Temporary for C code to call:
31 //go:linkname gwrite
32 //go:linkname printhex
34 // The compiler knows that a print of a value of this type
35 // should use printhex instead of printuint (decimal).
36 type hex uint64
38 //go:nowritebarrier
39 func bytes(s string) (ret []byte) {
40 rp := (*slice)(unsafe.Pointer(&ret))
41 sp := stringStructOf(&s)
42 rp.array = sp.str
43 rp.len = sp.len
44 rp.cap = sp.len
45 return
48 var (
49 // printBacklog is a circular buffer of messages written with the builtin
50 // print* functions, for use in postmortem analysis of core dumps.
51 printBacklog [512]byte
52 printBacklogIndex int
55 // recordForPanic maintains a circular buffer of messages written by the
56 // runtime leading up to a process crash, allowing the messages to be
57 // extracted from a core dump.
59 // The text written during a process crash (following "panic" or "fatal
60 // error") is not saved, since the goroutine stacks will generally be readable
61 // from the runtime datastructures in the core file.
62 func recordForPanic(b []byte) {
63 printlock()
65 if atomic.Load(&panicking) == 0 {
66 // Not actively crashing: maintain circular buffer of print output.
67 for i := 0; i < len(b); {
68 n := copy(printBacklog[printBacklogIndex:], b[i:])
69 i += n
70 printBacklogIndex += n
71 printBacklogIndex %= len(printBacklog)
75 printunlock()
78 var debuglock mutex
80 // The compiler emits calls to printlock and printunlock around
81 // the multiple calls that implement a single Go print or println
82 // statement. Some of the print helpers (printslice, for example)
83 // call print recursively. There is also the problem of a crash
84 // happening during the print routines and needing to acquire
85 // the print lock to print information about the crash.
86 // For both these reasons, let a thread acquire the printlock 'recursively'.
88 func printlock() {
89 mp := getg().m
90 mp.locks++ // do not reschedule between printlock++ and lock(&debuglock).
91 mp.printlock++
92 if mp.printlock == 1 {
93 lock(&debuglock)
95 mp.locks-- // now we know debuglock is held and holding up mp.locks for us.
98 func printunlock() {
99 mp := getg().m
100 mp.printlock--
101 if mp.printlock == 0 {
102 unlock(&debuglock)
106 // write to goroutine-local buffer if diverting output,
107 // or else standard error.
108 func gwrite(b []byte) {
109 if len(b) == 0 {
110 return
112 recordForPanic(b)
113 gp := getg()
114 // Don't use the writebuf if gp.m is dying. We want anything
115 // written through gwrite to appear in the terminal rather
116 // than be written to in some buffer, if we're in a panicking state.
117 // Note that we can't just clear writebuf in the gp.m.dying case
118 // because a panic isn't allowed to have any write barriers.
119 if gp == nil || gp.writebuf == nil || gp.m.dying > 0 {
120 writeErr(b)
121 return
124 n := copy(gp.writebuf[len(gp.writebuf):cap(gp.writebuf)], b)
125 gp.writebuf = gp.writebuf[:len(gp.writebuf)+n]
128 func printsp() {
129 printstring(" ")
132 func printnl() {
133 printstring("\n")
136 func printbool(v bool) {
137 if v {
138 printstring("true")
139 } else {
140 printstring("false")
144 func printfloat(v float64) {
145 switch {
146 case v != v:
147 printstring("NaN")
148 return
149 case v+v == v && v > 0:
150 printstring("+Inf")
151 return
152 case v+v == v && v < 0:
153 printstring("-Inf")
154 return
157 const n = 7 // digits printed
158 var buf [n + 7]byte
159 buf[0] = '+'
160 e := 0 // exp
161 if v == 0 {
162 if 1/v < 0 {
163 buf[0] = '-'
165 } else {
166 if v < 0 {
167 v = -v
168 buf[0] = '-'
171 // normalize
172 for v >= 10 {
174 v /= 10
176 for v < 1 {
178 v *= 10
181 // round
182 h := 5.0
183 for i := 0; i < n; i++ {
184 h /= 10
186 v += h
187 if v >= 10 {
189 v /= 10
193 // format +d.dddd+edd
194 for i := 0; i < n; i++ {
195 s := int(v)
196 buf[i+2] = byte(s + '0')
197 v -= float64(s)
198 v *= 10
200 buf[1] = buf[2]
201 buf[2] = '.'
203 buf[n+2] = 'e'
204 buf[n+3] = '+'
205 if e < 0 {
206 e = -e
207 buf[n+3] = '-'
210 buf[n+4] = byte(e/100) + '0'
211 buf[n+5] = byte(e/10)%10 + '0'
212 buf[n+6] = byte(e%10) + '0'
213 gwrite(buf[:])
216 func printcomplex(c complex128) {
217 print("(", real(c), imag(c), "i)")
220 func printuint(v uint64) {
221 var buf [100]byte
222 i := len(buf)
223 for i--; i > 0; i-- {
224 buf[i] = byte(v%10 + '0')
225 if v < 10 {
226 break
228 v /= 10
230 gwrite(buf[i:])
233 func printint(v int64) {
234 if v < 0 {
235 printstring("-")
236 v = -v
238 printuint(uint64(v))
241 var minhexdigits = 0 // protected by printlock
243 func printhex(v uint64) {
244 const dig = "0123456789abcdef"
245 var buf [100]byte
246 i := len(buf)
247 for i--; i > 0; i-- {
248 buf[i] = dig[v%16]
249 if v < 16 && len(buf)-i >= minhexdigits {
250 break
252 v /= 16
255 buf[i] = 'x'
257 buf[i] = '0'
258 gwrite(buf[i:])
261 func printpointer(p unsafe.Pointer) {
262 printhex(uint64(uintptr(p)))
264 func printuintptr(p uintptr) {
265 printhex(uint64(p))
268 func printstring(s string) {
269 gwrite(bytes(s))
272 func printslice(s []byte) {
273 sp := (*slice)(unsafe.Pointer(&s))
274 print("[", len(s), "/", cap(s), "]")
275 printpointer(sp.array)
278 func printeface(e eface) {
279 print("(", e._type, ",", e.data, ")")
282 func printiface(i iface) {
283 print("(", i.tab, ",", i.data, ")")
286 // hexdumpWords prints a word-oriented hex dump of [p, end).
288 // If mark != nil, it will be called with each printed word's address
289 // and should return a character mark to appear just before that
290 // word's value. It can return 0 to indicate no mark.
291 func hexdumpWords(p, end uintptr, mark func(uintptr) byte) {
292 printlock()
293 var markbuf [1]byte
294 markbuf[0] = ' '
295 minhexdigits = int(unsafe.Sizeof(uintptr(0)) * 2)
296 for i := uintptr(0); p+i < end; i += goarch.PtrSize {
297 if i%16 == 0 {
298 if i != 0 {
299 println()
301 print(hex(p+i), ": ")
304 if mark != nil {
305 markbuf[0] = mark(p + i)
306 if markbuf[0] == 0 {
307 markbuf[0] = ' '
310 gwrite(markbuf[:])
311 val := *(*uintptr)(unsafe.Pointer(p + i))
312 print(hex(val))
313 print(" ")
315 // Can we symbolize val?
316 name, _, _, _ := funcfileline(val, -1, false)
317 if name != "" {
318 entry := funcentry(val)
319 print("<", name, "+", hex(val-entry), "> ")
322 minhexdigits = 0
323 println()
324 printunlock()