gcc/libgo/go/runtime/print.go
Ian Lance Taylor 65180edc56 runtime: copy print/println support from Go 1.7
Update the compiler to use the new names.  Add calls to printlock and
    printunlock around print statements.  Move expression evaluation before
    the call to printlock.  Update g's writebuf field to a slice, and adjust
    C code accordingly.
    
    Reviewed-on: https://go-review.googlesource.com/30717

From-SVN: r240956
2016-10-10 23:13:39 +00:00

239 lines
4.4 KiB
Go

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package runtime
import "unsafe"
// For gccgo, use go:linkname to rename compiler-called functions to
// themselves, so that the compiler will export them.
//
//go:linkname printbool runtime.printbool
//go:linkname printfloat runtime.printfloat
//go:linkname printint runtime.printint
//go:linkname printhex runtime.printhex
//go:linkname printuint runtime.printuint
//go:linkname printcomplex runtime.printcomplex
//go:linkname printstring runtime.printstring
//go:linkname printpointer runtime.printpointer
//go:linkname printiface runtime.printiface
//go:linkname printeface runtime.printeface
//go:linkname printslice runtime.printslice
//go:linkname printnl runtime.printnl
//go:linkname printsp runtime.printsp
//go:linkname printlock runtime.printlock
//go:linkname printunlock runtime.printunlock
// Temporary for C code to call:
//go:linkname gwrite runtime.gwrite
//go:linkname printhex runtime.printhex
// The compiler knows that a print of a value of this type
// should use printhex instead of printuint (decimal).
type hex uint64
func bytes(s string) (ret []byte) {
rp := (*slice)(unsafe.Pointer(&ret))
sp := stringStructOf(&s)
rp.array = sp.str
rp.len = sp.len
rp.cap = sp.len
return
}
var debuglock mutex
// The compiler emits calls to printlock and printunlock around
// the multiple calls that implement a single Go print or println
// statement. Some of the print helpers (printsp, for example)
// call print recursively. There is also the problem of a crash
// happening during the print routines and needing to acquire
// the print lock to print information about the crash.
// For both these reasons, let a thread acquire the printlock 'recursively'.
func printlock() {
mp := getg().m
mp.locks++ // do not reschedule between printlock++ and lock(&debuglock).
mp.printlock++
if mp.printlock == 1 {
lock(&debuglock)
}
mp.locks-- // now we know debuglock is held and holding up mp.locks for us.
}
func printunlock() {
mp := getg().m
mp.printlock--
if mp.printlock == 0 {
unlock(&debuglock)
}
}
// write to goroutine-local buffer if diverting output,
// or else standard error.
func gwrite(b []byte) {
if len(b) == 0 {
return
}
gp := getg()
if gp == nil || gp.writebuf == nil {
writeErr(b)
return
}
n := copy(gp.writebuf[len(gp.writebuf):cap(gp.writebuf)], b)
gp.writebuf = gp.writebuf[:len(gp.writebuf)+n]
}
func printsp() {
print(" ")
}
func printnl() {
print("\n")
}
func printbool(v bool) {
if v {
print("true")
} else {
print("false")
}
}
func printfloat(v float64) {
switch {
case v != v:
print("NaN")
return
case v+v == v && v > 0:
print("+Inf")
return
case v+v == v && v < 0:
print("-Inf")
return
}
const n = 7 // digits printed
var buf [n + 7]byte
buf[0] = '+'
e := 0 // exp
if v == 0 {
if 1/v < 0 {
buf[0] = '-'
}
} else {
if v < 0 {
v = -v
buf[0] = '-'
}
// normalize
for v >= 10 {
e++
v /= 10
}
for v < 1 {
e--
v *= 10
}
// round
h := 5.0
for i := 0; i < n; i++ {
h /= 10
}
v += h
if v >= 10 {
e++
v /= 10
}
}
// format +d.dddd+edd
for i := 0; i < n; i++ {
s := int(v)
buf[i+2] = byte(s + '0')
v -= float64(s)
v *= 10
}
buf[1] = buf[2]
buf[2] = '.'
buf[n+2] = 'e'
buf[n+3] = '+'
if e < 0 {
e = -e
buf[n+3] = '-'
}
buf[n+4] = byte(e/100) + '0'
buf[n+5] = byte(e/10)%10 + '0'
buf[n+6] = byte(e%10) + '0'
gwrite(buf[:])
}
func printcomplex(c complex128) {
print("(", real(c), imag(c), "i)")
}
func printuint(v uint64) {
var buf [100]byte
i := len(buf)
for i--; i > 0; i-- {
buf[i] = byte(v%10 + '0')
if v < 10 {
break
}
v /= 10
}
gwrite(buf[i:])
}
func printint(v int64) {
if v < 0 {
print("-")
v = -v
}
printuint(uint64(v))
}
func printhex(v uint64) {
const dig = "0123456789abcdef"
var buf [100]byte
i := len(buf)
for i--; i > 0; i-- {
buf[i] = dig[v%16]
if v < 16 {
break
}
v /= 16
}
i--
buf[i] = 'x'
i--
buf[i] = '0'
gwrite(buf[i:])
}
func printpointer(p unsafe.Pointer) {
printhex(uint64(uintptr(p)))
}
func printstring(s string) {
gwrite(bytes(s))
}
func printslice(s []byte) {
sp := (*slice)(unsafe.Pointer(&s))
print("[", len(s), "/", cap(s), "]")
printpointer(sp.array)
}
func printeface(e eface) {
print("(", e._type, ",", e.data, ")")
}
func printiface(i iface) {
print("(", i.tab, ",", i.data, ")")
}