runtime: scan register backing store on ia64
[official-gcc.git] / libgo / go / runtime / print.go
blob3da05ad5f9e017345cad19de67cddbf035ac93de
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 "runtime/internal/atomic"
9 "unsafe"
12 // For gccgo, use go:linkname to rename compiler-called functions to
13 // themselves, so that the compiler will export them.
15 //go:linkname printbool runtime.printbool
16 //go:linkname printfloat runtime.printfloat
17 //go:linkname printint runtime.printint
18 //go:linkname printhex runtime.printhex
19 //go:linkname printuint runtime.printuint
20 //go:linkname printcomplex runtime.printcomplex
21 //go:linkname printstring runtime.printstring
22 //go:linkname printpointer runtime.printpointer
23 //go:linkname printiface runtime.printiface
24 //go:linkname printeface runtime.printeface
25 //go:linkname printslice runtime.printslice
26 //go:linkname printnl runtime.printnl
27 //go:linkname printsp runtime.printsp
28 //go:linkname printlock runtime.printlock
29 //go:linkname printunlock runtime.printunlock
30 // Temporary for C code to call:
31 //go:linkname gwrite runtime.gwrite
32 //go:linkname printhex runtime.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 func bytes(s string) (ret []byte) {
39 rp := (*slice)(unsafe.Pointer(&ret))
40 sp := stringStructOf(&s)
41 rp.array = sp.str
42 rp.len = sp.len
43 rp.cap = sp.len
44 return
47 var (
48 // printBacklog is a circular buffer of messages written with the builtin
49 // print* functions, for use in postmortem analysis of core dumps.
50 printBacklog [512]byte
51 printBacklogIndex int
54 // recordForPanic maintains a circular buffer of messages written by the
55 // runtime leading up to a process crash, allowing the messages to be
56 // extracted from a core dump.
58 // The text written during a process crash (following "panic" or "fatal
59 // error") is not saved, since the goroutine stacks will generally be readable
60 // from the runtime datastructures in the core file.
61 func recordForPanic(b []byte) {
62 printlock()
64 if atomic.Load(&panicking) == 0 {
65 // Not actively crashing: maintain circular buffer of print output.
66 for i := 0; i < len(b); {
67 n := copy(printBacklog[printBacklogIndex:], b[i:])
68 i += n
69 printBacklogIndex += n
70 printBacklogIndex %= len(printBacklog)
74 printunlock()
77 var debuglock mutex
79 // The compiler emits calls to printlock and printunlock around
80 // the multiple calls that implement a single Go print or println
81 // statement. Some of the print helpers (printslice, for example)
82 // call print recursively. There is also the problem of a crash
83 // happening during the print routines and needing to acquire
84 // the print lock to print information about the crash.
85 // For both these reasons, let a thread acquire the printlock 'recursively'.
87 func printlock() {
88 mp := getg().m
89 mp.locks++ // do not reschedule between printlock++ and lock(&debuglock).
90 mp.printlock++
91 if mp.printlock == 1 {
92 lock(&debuglock)
94 mp.locks-- // now we know debuglock is held and holding up mp.locks for us.
97 func printunlock() {
98 mp := getg().m
99 mp.printlock--
100 if mp.printlock == 0 {
101 unlock(&debuglock)
105 // write to goroutine-local buffer if diverting output,
106 // or else standard error.
107 func gwrite(b []byte) {
108 if len(b) == 0 {
109 return
111 recordForPanic(b)
112 gp := getg()
113 if gp == nil || gp.writebuf == nil {
114 writeErr(b)
115 return
118 n := copy(gp.writebuf[len(gp.writebuf):cap(gp.writebuf)], b)
119 gp.writebuf = gp.writebuf[:len(gp.writebuf)+n]
122 func printsp() {
123 printstring(" ")
126 func printnl() {
127 printstring("\n")
130 func printbool(v bool) {
131 if v {
132 printstring("true")
133 } else {
134 printstring("false")
138 func printfloat(v float64) {
139 switch {
140 case v != v:
141 printstring("NaN")
142 return
143 case v+v == v && v > 0:
144 printstring("+Inf")
145 return
146 case v+v == v && v < 0:
147 printstring("-Inf")
148 return
151 const n = 7 // digits printed
152 var buf [n + 7]byte
153 buf[0] = '+'
154 e := 0 // exp
155 if v == 0 {
156 if 1/v < 0 {
157 buf[0] = '-'
159 } else {
160 if v < 0 {
161 v = -v
162 buf[0] = '-'
165 // normalize
166 for v >= 10 {
168 v /= 10
170 for v < 1 {
172 v *= 10
175 // round
176 h := 5.0
177 for i := 0; i < n; i++ {
178 h /= 10
180 v += h
181 if v >= 10 {
183 v /= 10
187 // format +d.dddd+edd
188 for i := 0; i < n; i++ {
189 s := int(v)
190 buf[i+2] = byte(s + '0')
191 v -= float64(s)
192 v *= 10
194 buf[1] = buf[2]
195 buf[2] = '.'
197 buf[n+2] = 'e'
198 buf[n+3] = '+'
199 if e < 0 {
200 e = -e
201 buf[n+3] = '-'
204 buf[n+4] = byte(e/100) + '0'
205 buf[n+5] = byte(e/10)%10 + '0'
206 buf[n+6] = byte(e%10) + '0'
207 gwrite(buf[:])
210 func printcomplex(c complex128) {
211 print("(", real(c), imag(c), "i)")
214 func printuint(v uint64) {
215 var buf [100]byte
216 i := len(buf)
217 for i--; i > 0; i-- {
218 buf[i] = byte(v%10 + '0')
219 if v < 10 {
220 break
222 v /= 10
224 gwrite(buf[i:])
227 func printint(v int64) {
228 if v < 0 {
229 printstring("-")
230 v = -v
232 printuint(uint64(v))
235 func printhex(v uint64) {
236 const dig = "0123456789abcdef"
237 var buf [100]byte
238 i := len(buf)
239 for i--; i > 0; i-- {
240 buf[i] = dig[v%16]
241 if v < 16 {
242 break
244 v /= 16
247 buf[i] = 'x'
249 buf[i] = '0'
250 gwrite(buf[i:])
253 func printpointer(p unsafe.Pointer) {
254 printhex(uint64(uintptr(p)))
257 func printstring(s string) {
258 gwrite(bytes(s))
261 func printslice(s []byte) {
262 sp := (*slice)(unsafe.Pointer(&s))
263 print("[", len(s), "/", cap(s), "]")
264 printpointer(sp.array)
267 func printeface(e eface) {
268 print("(", e._type, ",", e.data, ")")
271 func printiface(i iface) {
272 print("(", i.tab, ",", i.data, ")")