print.mx raw

   1  package runtime
   2  
   3  import (
   4  	"unsafe"
   5  )
   6  
   7  type stringer interface {
   8  	String() string
   9  }
  10  
  11  //go:nobounds
  12  func printstring(s string) {
  13  	for i := 0; i < len(s); i++ {
  14  		putchar(s[i])
  15  	}
  16  }
  17  
  18  func printuint8(n uint8) {
  19  	if TargetBits >= 32 {
  20  		printuint32(uint32(n))
  21  	} else {
  22  		prevdigits := n / 10
  23  		if prevdigits != 0 {
  24  			printuint8(prevdigits)
  25  		}
  26  		putchar(byte((n % 10) + '0'))
  27  	}
  28  }
  29  
  30  func printint8(n int8) {
  31  	if TargetBits >= 32 {
  32  		printint32(int32(n))
  33  	} else {
  34  		if n < 0 {
  35  			putchar('-')
  36  			n = -n
  37  		}
  38  		printuint8(uint8(n))
  39  	}
  40  }
  41  
  42  func printuintptr(n uintptr) {
  43  	switch unsafe.Sizeof(n) {
  44  	case 2:
  45  		printuint16(uint16(n))
  46  	case 4:
  47  		printuint32(uint32(n))
  48  	case 8:
  49  		printuint64(uint64(n))
  50  	}
  51  }
  52  
  53  func printuint16(n uint16) {
  54  	printuint32(uint32(n))
  55  }
  56  
  57  func printint16(n int16) {
  58  	printint32(int32(n))
  59  }
  60  
  61  func printuint32(n uint32) {
  62  	printuint64(uint64(n))
  63  }
  64  
  65  func printint32(n int32) {
  66  	// Print integer in signed big-endian base-10 notation, for humans to
  67  	// read.
  68  	if n < 0 {
  69  		putchar('-')
  70  		n = -n
  71  	}
  72  	printuint32(uint32(n))
  73  }
  74  
  75  //go:nobounds
  76  func printuint64(n uint64) {
  77  	digits := [20]byte{} // enough to hold (2^64)-1
  78  	// Fill in all 10 digits.
  79  	firstdigit := 19 // digit index that isn't zero (by default, the last to handle '0' correctly)
  80  	for i := 19; i >= 0; i-- {
  81  		digit := byte(n%10 + '0')
  82  		digits[i] = digit
  83  		if digit != '0' {
  84  			firstdigit = i
  85  		}
  86  		n /= 10
  87  	}
  88  	// Print digits without the leading zeroes.
  89  	for i := firstdigit; i < 20; i++ {
  90  		putchar(digits[i])
  91  	}
  92  }
  93  
  94  func printint64(n int64) {
  95  	if n < 0 {
  96  		putchar('-')
  97  		n = -n
  98  	}
  99  	printuint64(uint64(n))
 100  }
 101  
 102  // printfloat32() was copied from the relevant source in the original Go
 103  // implementation and modified to work with float32 instead of float64. It is
 104  // copyright by the Go authors, licensed under the same BSD 3-clause license.
 105  // See https://golang.org/LICENSE for details.
 106  //
 107  // It is a near-duplicate of printfloat64. This is done so that printing a
 108  // float32 value doesn't involve float64 routines, which can be unexpected and a
 109  // problem sometimes. It comes with a possible code size reduction if both
 110  // printfloat32 and printfloat64 are used, which seems uncommon.
 111  //
 112  // Source:
 113  // https://github.com/golang/go/blob/master/src/runtime/print.go
 114  func printfloat32(v float32) {
 115  	switch {
 116  	case v != v:
 117  		printstring("NaN")
 118  		return
 119  	case v+v == v && v > 0:
 120  		printstring("+Inf")
 121  		return
 122  	case v+v == v && v < 0:
 123  		printstring("-Inf")
 124  		return
 125  	}
 126  
 127  	const n = 7 // digits printed
 128  	var buf [n + 7]byte
 129  	buf[0] = '+'
 130  	e := 0 // exp
 131  	if v == 0 {
 132  		if 1/v < 0 {
 133  			buf[0] = '-'
 134  		}
 135  	} else {
 136  		if v < 0 {
 137  			v = -v
 138  			buf[0] = '-'
 139  		}
 140  
 141  		// normalize
 142  		for v >= 10 {
 143  			e++
 144  			v /= 10
 145  		}
 146  		for v < 1 {
 147  			e--
 148  			v *= 10
 149  		}
 150  
 151  		// round
 152  		h := float32(5.0)
 153  		for i := 0; i < n; i++ {
 154  			h /= 10
 155  		}
 156  		v += h
 157  		if v >= 10 {
 158  			e++
 159  			v /= 10
 160  		}
 161  	}
 162  
 163  	// format +d.dddd+edd
 164  	for i := 0; i < n; i++ {
 165  		s := int(v)
 166  		buf[i+2] = byte(s + '0')
 167  		v -= float32(s)
 168  		v *= 10
 169  	}
 170  	buf[1] = buf[2]
 171  	buf[2] = '.'
 172  
 173  	buf[n+2] = 'e'
 174  	buf[n+3] = '+'
 175  	if e < 0 {
 176  		e = -e
 177  		buf[n+3] = '-'
 178  	}
 179  
 180  	buf[n+4] = byte(e/100) + '0'
 181  	buf[n+5] = byte(e/10)%10 + '0'
 182  	buf[n+6] = byte(e%10) + '0'
 183  	for _, c := range buf {
 184  		putchar(c)
 185  	}
 186  }
 187  
 188  // printfloat64() was copied from the relevant source in the original Go
 189  // implementation. It is copyright by the Go authors, licensed under the same
 190  // BSD 3-clause license. See https://golang.org/LICENSE for details.
 191  //
 192  // Source:
 193  // https://github.com/golang/go/blob/master/src/runtime/print.go
 194  func printfloat64(v float64) {
 195  	switch {
 196  	case v != v:
 197  		printstring("NaN")
 198  		return
 199  	case v+v == v && v > 0:
 200  		printstring("+Inf")
 201  		return
 202  	case v+v == v && v < 0:
 203  		printstring("-Inf")
 204  		return
 205  	}
 206  
 207  	const n = 7 // digits printed
 208  	var buf [n + 7]byte
 209  	buf[0] = '+'
 210  	e := 0 // exp
 211  	if v == 0 {
 212  		if 1/v < 0 {
 213  			buf[0] = '-'
 214  		}
 215  	} else {
 216  		if v < 0 {
 217  			v = -v
 218  			buf[0] = '-'
 219  		}
 220  
 221  		// normalize
 222  		for v >= 10 {
 223  			e++
 224  			v /= 10
 225  		}
 226  		for v < 1 {
 227  			e--
 228  			v *= 10
 229  		}
 230  
 231  		// round
 232  		h := 5.0
 233  		for i := 0; i < n; i++ {
 234  			h /= 10
 235  		}
 236  		v += h
 237  		if v >= 10 {
 238  			e++
 239  			v /= 10
 240  		}
 241  	}
 242  
 243  	// format +d.dddd+edd
 244  	for i := 0; i < n; i++ {
 245  		s := int(v)
 246  		buf[i+2] = byte(s + '0')
 247  		v -= float64(s)
 248  		v *= 10
 249  	}
 250  	buf[1] = buf[2]
 251  	buf[2] = '.'
 252  
 253  	buf[n+2] = 'e'
 254  	buf[n+3] = '+'
 255  	if e < 0 {
 256  		e = -e
 257  		buf[n+3] = '-'
 258  	}
 259  
 260  	buf[n+4] = byte(e/100) + '0'
 261  	buf[n+5] = byte(e/10)%10 + '0'
 262  	buf[n+6] = byte(e%10) + '0'
 263  	for _, c := range buf {
 264  		putchar(c)
 265  	}
 266  }
 267  
 268  func printcomplex64(c complex64) {
 269  	putchar('(')
 270  	printfloat32(real(c))
 271  	printfloat32(imag(c))
 272  	printstring("i)")
 273  }
 274  
 275  func printcomplex128(c complex128) {
 276  	putchar('(')
 277  	printfloat64(real(c))
 278  	printfloat64(imag(c))
 279  	printstring("i)")
 280  }
 281  
 282  // printbytes prints a []byte as text, used by print([]byte(...)).
 283  //
 284  //go:nobounds
 285  func printbytes(b []byte) {
 286  	for i := 0; i < len(b); i++ {
 287  		putchar(b[i])
 288  	}
 289  }
 290  
 291  func printspace() {
 292  	putchar(' ')
 293  }
 294  
 295  func printnl() {
 296  	if baremetal {
 297  		putchar('\r')
 298  	}
 299  	putchar('\n')
 300  }
 301  
 302  func printitf(msg interface{}) {
 303  	switch msg := msg.(type) {
 304  	case bool:
 305  		printbool(msg)
 306  	case int:
 307  		printint32(int32(msg))
 308  	case int8:
 309  		printint8(msg)
 310  	case int16:
 311  		printint16(msg)
 312  	case int64:
 313  		printint64(msg)
 314  	case uint:
 315  		printuint32(uint32(msg))
 316  	case uint8:
 317  		printuint8(msg)
 318  	case uint16:
 319  		printuint16(msg)
 320  	case uint64:
 321  		printuint64(msg)
 322  	case uintptr:
 323  		printuintptr(msg)
 324  	case float32:
 325  		printfloat32(msg)
 326  	case float64:
 327  		printfloat64(msg)
 328  	case complex64:
 329  		printcomplex64(msg)
 330  	case complex128:
 331  		printcomplex128(msg)
 332  	case string:
 333  		printstring(msg)
 334  	case error:
 335  		printstring(msg.Error())
 336  	case stringer:
 337  		printstring(msg.String())
 338  	default:
 339  		// cast to underlying type
 340  		itf := *(*_interface)(unsafe.Pointer(&msg))
 341  		putchar('(')
 342  		printuintptr(uintptr(itf.typecode))
 343  		putchar(':')
 344  		printptr(uintptr(itf.value))
 345  		putchar(')')
 346  	}
 347  }
 348  
 349  func printmap(m *hashmap) {
 350  	printstring("map[")
 351  	if m == nil {
 352  		printstring("nil")
 353  	} else {
 354  		switch unsafe.Sizeof(m.count) {
 355  		case 8:
 356  			printuint64(uint64(m.count))
 357  		case 4:
 358  			printuint32(uint32(m.count))
 359  		case 2:
 360  			printuint16(uint16(m.count))
 361  		}
 362  	}
 363  	putchar(']')
 364  }
 365  
 366  func printptr(ptr uintptr) {
 367  	if ptr == 0 {
 368  		printstring("nil")
 369  		return
 370  	}
 371  	putchar('0')
 372  	putchar('x')
 373  	for i := 0; i < int(unsafe.Sizeof(ptr))*2; i++ {
 374  		nibble := byte(ptr >> (unsafe.Sizeof(ptr)*8 - 4))
 375  		if nibble < 10 {
 376  			putchar(nibble + '0')
 377  		} else {
 378  			putchar(nibble - 10 + 'a')
 379  		}
 380  		ptr <<= 4
 381  	}
 382  }
 383  
 384  func printbool(b bool) {
 385  	if b {
 386  		printstring("true")
 387  	} else {
 388  		printstring("false")
 389  	}
 390  }
 391  
 392  func printslice(ptr, len_, cap_ uintptr) {
 393  	putchar('[')
 394  	printuintptr(len_)
 395  	putchar('/')
 396  	printuintptr(cap_)
 397  	putchar(']')
 398  	printptr(ptr)
 399  }
 400